• 线程的synchronized、volatile及原子操作


    public class ThreadDemo7{
        //structs2线程不安全  共享变量
        //n++ 复合操作  对于volatile修饰的变量不安全
        //原子操作
        int  value;
    
        //让方法变成一个同步的方法
        public synchronized int nextValue(){
            return value ++;
        }
        public static void main(String[] args){
            ThreadDemo7 t1 = new ThreadDemo7();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true){
                        System.out.println(t1.nextValue() + " " + Thread.currentThread().getName());
                    }
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true){
                        System.out.println(t1.nextValue() + " " + Thread.currentThread().getName());
                    }
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true){
                        System.out.println(t1.nextValue() + " " + Thread.currentThread().getName());
                    }
                }
            }).start();
        }
    }
    public class ThreadDemo7_1 {
        private static volatile int num;
    
        //使用countDownLatch来等待使线程执行完
        public static CountDownLatch countDownLatch = new CountDownLatch(30);
    
        //由于n++是复合操作,所以并不能保证线程安全
        //public synchronized  int NextValue(){
        public int NextValue(){
            return num ++;
        }
        public static void main(String[] args){
            ThreadDemo7_1 t1 = new ThreadDemo7_1();
    
            for(int i=0;i<30;i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for(int j=0;j<10000;j++){
                            t1.NextValue();
                        }
                        countDownLatch.countDown();
                    }
                }).start();
            }
            try{
                countDownLatch.await();
            }catch (InterruptedException e){
                e.getMessage();
            }
    
            System.out.println(num);
        }
    }
    public class ThreadDemo7_2 {
        private static AtomicInteger num = new AtomicInteger();
    
        //使用countDownLatch来等待使线程执行完
        public static CountDownLatch countDownLatch = new CountDownLatch(30);
    
        public static void main(String[] args){
            ThreadDemo7_1 t1 = new ThreadDemo7_1();
    
            for(int i=0;i<30;i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for(int j=0;j<10000;j++){
                            num.incrementAndGet(); //原子性的num++,通过cas方式
                        }
                        countDownLatch.countDown();
                    }
                }).start();
            }
            try{
                countDownLatch.await();
            }catch (InterruptedException e){
                e.getMessage();
            }
    
            System.out.println(num);
        }

    概念解析

    并发机制依赖于JVM的实现和CPU的指令
    1. volatile一般在多线程中使用,保证共享变量的可见性,解决并发带来的问题
    可见性意思就是一个线程修改另外一个线程可以看到修改后的值,通过排它锁单独获得这个变量
    volatile执行成本低,因为不会引起线程上下文的切换和调度
    synchronized是重量级锁
    2. volatile深层理解
    有volatile变量修饰的共享变量进行读写操作的时候会多出第二行汇编代码
    lock前缀的指令在多核处理器下会引发两件事情:
    1)lock前缀指令会引起处理器缓存回写到内存
    2)这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效
    3. synchronized实现同步的基础:java中的每一个对象都可以作为锁
    具体表现如下:
    1)对于普通同步方法,锁是当前实例对象
    2)对于静态同步方法,锁是当前类的class对象
    3)对于同步方法块,锁是synchronized括号里配置的对象
    当一个线程视图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁
    Synchronized在JVM里的实现原理:JVM基于进入和退出Monitor对象来实现方法同步和代码块同步
    2. 无锁,偏向锁,轻量级锁,重量级锁

  • 相关阅读:
    Explicitly configure spring.jpa.open-in-view to disable this warning
    [LeetCode] 982. Triples with Bitwise AND Equal To Zero 按位与为零的三元组
    [LeetCode] 981. Time Based Key-Value Store 基于时间的键值存储
    [LeetCode] 980. Unique Paths III 不同的路径之三
    [LeetCode] 979. Distribute Coins in Binary Tree 在二叉树中分配硬币
    [LeetCode] 978. Longest Turbulent Subarray 最长湍流子数组
    [LeetCode] 976. Largest Perimeter Triangle 最大周长的三角形
    [LeetCode] 977. Squares of a Sorted Array 有序数组的平方值
    [LeetCode] 975. Odd Even Jump 奇偶跳跃
    [LeetCode] 974. Subarray Sums Divisible by K 子数组数字之和可被K整除
  • 原文地址:https://www.cnblogs.com/mutong1228/p/10491851.html
Copyright © 2020-2023  润新知