并发线程安全

出现线程安全问题的原因:

1、原子性:不同线程对共享变量非原子读写

2、可见性:不同线程使用共享变量时会从主存中复制一份共享变量的副本到自己的本地内存中,副本被修改后不会及时刷新到主存中,其他线程获取到的是未修改时的值

3、有序性:CPU为了执行效率,会把CPU指令进行重新排序,单线程重排序后的执行结果与代码顺序预期的结果一致,多线程重排序则可能会导致运行结果与预期结果不一致

解决方法:

1、原子性:使用synchronized加锁

                    ②循环CAS(Compare and Swap)操作(Lock和原子类(AtomicInteger、AtomicReference))

     例:static ReentrantLock lock = new ReentrantLock ();

             lock.lock();        //加锁

             count++;

             lock.unlock();    //解锁

             static AtomicInteger count = new AtomicInteger(0);

             count.incrementAndGet(); //自增

             count.decrementAndGet(); //自减

2、可见性:

加锁,synchronized和Lock都可以保证(JMM中规定了,lock操作会从主存中刷新最新共享变量的值到工作线程,而unlock会将工作线程中的值同步会主存。所以synchronized可以保证可见性)

import java.util.concurrent.CountDownLatch;

public class SychronizedTest {

    public static int value = 1;
    public static int value2 = 1;

    public static void main(String[] args) {

        CountDownLatch countDownLatch = new CountDownLatch(1000);

        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                value2++;
                synchronized(SychronizedTest.class){
                    value++;
                }
                countDownLatch.countDown();
            }).start();
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("============");
        System.out.println(value);
        System.out.println(value2);
        System.out.println("============");

    }

}

多运行几次出现一下结果:

使用volatile修饰共享变量(修改后会立即刷新到主存,读取变量值时会从主存重新获取)

3、有序性:

使用volatile修饰变量,被修饰变量读写操作时会保证前面的代码指令已经执行且后面的代码未执行

例:单例模式时防止重排序

class Singleton {
    private volatile static Singleton instance;
    public static Singleton getInstance() {
        if ( instance == null ) { //这里存在竞态条件
            instance = new Singleton();
        }
        return instance;
    }
}

加锁,synchronized(synchronized代码块内部不保证有序性,与代码块前后保证有序性)

参考:【JAVA并发第四篇】线程安全 - 就行222 - 博客园

http://t.csdn.cn/GUGjD

                    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值