多线程学习笔记-3

Atomic

使用锁可以保证原子性,但是带来会上下文切换和线程调度的开销,CAS(compare and swap)是jdk提供的非阻塞操作,通过硬件保证比较-更新的原子性

class A{
    AtomicInteger v=new AtomicInteger();
    int x;
}
public class Main{
    public static void main(String[] args) throws InterruptedException {
        int cnt=50000;
        CountDownLatch countDownLatch=new CountDownLatch(cnt);
        A a = new A();
        for (int i = 0; i < cnt; i++) {
            new Thread(()->{
                a.x++;
                a.v.incrementAndGet();
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println(a.v);
        System.out.println(a.x);
    }
}

volatile

保证内存可见性,不保证原子性,synchronized既保证原子性又保证可见性

什么时候用

  • 更新变量时,不依赖变量当前值。如果依赖变量当前值,则修改有三步,读-计算-写入,也就是需要保证原子性,而volatile不能保证原子性
  • 读写变量时,没有加锁。因为加锁本身保证内存可见性,没有必要声明为volatile

threadlocal

不同线程各自保存一个数据副本,每个线程只能访问修改自己的数据副本

class A{
    String s;
    void setV(String v){
        this.s=v;
    }
    String getV(){
        return s;
    }
}
public class Main{
    public static void main(String[] args) {
        A a = new A();
        for (int i = 0; i < 8; i++) {
            new Thread(()->{
                a.setV(Thread.currentThread().getName());
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(a.getV());
            }).start();
        }
    }
}
class A{
    ThreadLocal<String> s=new ThreadLocal<>();
}
public class Main{
    public static void main(String[] args) {
        A a = new A();
        for (int i = 0; i < 8; i++) {
            new Thread(()->{
                a.s.set(Thread.currentThread().getName());
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(a.s.get());
            }).start();
        }
    }
}

Semaphore

限制同时执行线程数量

public class Main{
    public static void main(String[] args) {
        Semaphore semaphore=new Semaphore(3);//最多3个线程一起执行,其他线程阻塞
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"完成");
                semaphore.release();
            }).start();
        }
    }
}

CountDownLatch

等待若干个子任务线程都完成后,调用线程才继续往下执行

public class Main{
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch=new CountDownLatch(3);
        for (int i = 0; i < 3; i++) {
            final int finalI=i;
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(finalI);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"完成");
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println("全部完成");
    }
}

CyclicBarrier

多个线程都到达一个屏障后,一同继续向下执行

public class Main{
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier=new CyclicBarrier(3,()->{
            System.out.println("全部线程达到屏障");
        });
        for (int i = 0; i < 3; i++) {
            final int I=i;
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(I);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"到达屏障");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"继续...");
            }).start();
        }
    }
}
posted @ 2021-04-16 15:47  我吃水煮虾  阅读(56)  评论(0)    收藏  举报