Java并发编程读书笔记——并发编程的简述

这是读这本书的第二遍,所以会在前面记录一些后面可能比较重要的点,也希望记录一下所学,能学到第一遍所不能理解和懵懂的东西...

1.上下文切换:

    计算机单核处理器也支持多线程,是因为CPU通过给每一个线程分配CPU的时间片,即每个线程占用CPU的时间,这个时间非常短,所以会让我们以为是多个线程同时执行的。

    当一个任务执行完当前的时间片,会保存当前的状态,等下一次切换回来的时候加载这个状态,以便继续执行。即任务从保存到再加载的过程就是一次上下文切换。

2.多线程并不一定比单线程快。

    上面说到多线程是通过上下文切换来实现的,每一次上下文切换仍需要时间,所以多线程并不一定比单线程快。书上列举了一段代码,以及测试的过程,结果是当并发执行累加操作不超过百万次时,速度会比串行执行累加操作要慢。

3.减少上下文切换。

    (1).无锁并发编程:采用一些方法来避免使用锁,如将数据的ID按照Hash算法去摸分段,不同的线程处理不同段的数据(ConcurrentHashMap的原理)

    (2).CAS算法(很重要,后边慢慢会说到,着急的可以先去查查CAS

    (3).使用最少的线程:这个就不用多说了,减少多余的线程。

    (4).协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。

4.死锁。

    死锁这个东西,有一点线程基础的人应该都听说过,个人觉得对于死锁,应该随手要能写出来,但是要极力的去避免它,做到这样就够了。下面就写一段简单的死锁的代码:

package com.concurrent.lock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DeadLockDemo {
    private static final Logger logger = LoggerFactory.getLogger(DeadLockDemo.class);
    private String A = "A";
    private String B = "B";

    public static void main(String[] args) {
        new DeadLockDemo().deadLock();
    }

    private void deadLock(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (A){    //当前线程握住A锁
                    try {
                        Thread.currentThread().sleep(2000);    //沉睡2S,不释放锁
                        logger.info("线程1:要执行的代码块1");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (B){    //要去获取B锁,但是由于沉睡2S,被线程2获取拿住
                        logger.info("线程1:要执行的代码块2");
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (B){    //当前线程握住B锁
                    try {
                        Thread.currentThread().sleep(2000);    //沉睡2S,不释放锁
                        logger.info("线程2:要执行的代码块1");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (A){        //要去获取A锁,但是被线程1握住
                        logger.info("线程2:要执行的代码块2");
                    }
                }
            }
        }).start();
    }

}

上面的两个线程一个握住A锁,一个握住B锁,都想要对方的锁,从而形成死锁,执行结果:


下面是后面学习记录的Java并发编程:

volatile、synchronized和原子操作(CAS机制详解)

Java内存模型(包括并发中的一些内存语义)

ThreadLocal

CountDownLatch、CyclicBarrier、Semaphore

解析Java中线程池的原理


猜你喜欢

转载自blog.csdn.net/crazer_cy/article/details/79616797
今日推荐