线程安全——原子性(synchronized)

package threading;
//线程安全
class Counter{
    public int count = 0;
    public void increase(){
        count++;
    }
}
public class Demo14 {
    //每个线程自增5W次
    public static Counter counter = new Counter();
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            for (int i = 0; i < 50000; i++) {
                counter.increase();
            }
        });

        Thread t2 = new Thread(()->{
            for (int i = 0; i < 50000; i++) {
                counter.increase();
            }
        });
        t1.start();
        t2.start();

        t1.join();
        t2.join();
        System.out.println("counter: "+counter.count);
    }
}

上述代码是创建两个线程,每个线程通过counter来进行5w次自增。最后预期的结果肯定是10w

运行后可以发现:每一次运行的结果都不一样。此时bug就出现了。

出现的bug原因如下:

进行的 count ++ 操作,底层是三条 指令 在 CPU 上完成的!!!

1)把内存的数据读取到 CPU 寄存器中     load

2)把 CPU 的寄存器中的值,进行 +1          add

3)把寄存器中的值,写回到内存中              save

因为并发的关系,线程之间的调度顺序不确定,而且是两个线程修改一个变量。

所以两个线程执行这些操作时就可能有多种执行的顺序。

(这两种排列顺序说没问题的)

等等等等等

除了前两种”串行执行“的情况,其他都是有问题的!

那第三个排序方法举个例子:

本来count=2的它给搞个1,这就说明有bug了。所以,有不确定的值。

如何解决嘞

这就要用到加锁的操作,把count++变成原子的(不会被线程调度机制打断的操作:跟原子一样,不可分嘛~):

在count++之前加锁,count++执行之后再解锁。

在加锁和解锁之间,进行修改,这个时候别的线程想要修改,不好意思,修改不了!!

(别的线程只能阻塞等待,阻塞等待的线程状态,BLOCKED 状态)

Java中,进行加锁,使用synchronized(读:心抠奈字的)

这样运行就是10_0000啦!

当然,synchronized也可以修饰代码块。

synchronized()里面填的东西就是你要针对那个对象加锁(锁对象)我这里用this就以为这谁调用increase方法谁就是this。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值