线程的安全问题(临界资源的解释),以及如何使线程安全、同步(方法)

什么是线程安全问题?

 当A和B两个线程,执行的方法都是向内存的一块数组中插入数据。当A找到数组下标为0的位置的时候,正准备插入a。。这时,时间片到了,到点了。B来了,它也找到数组下标为0的位置,它的时间比较充裕,B可以插入数据b。然后,A有时间片了,就会将a直接插入到数组小标为0的位置。所以此时数组小标为0的位置是a,b插入的数据就丢失了

 

多线程安全问题:

当多线程并发访问临界资源时,如果破坏原子操作(找位置,插入数据的操作),可能会造成数据不一致

什么是临界资源

临界资源:共享资源,就相当于上面讲的数组,一次仅允许一个线程使用,才可以保证其正确性

原子操作:不可分割的多步操作,被视作一个整体,其顺序和步骤不可打乱或缺省

 

 

举一个例子讲一下 线程安全的问题:

代码就是 创建AB两个线程,向数组中的同一个位置0进行插入数据的操作。打印的结果的可能性有3种:

第一种情况:先插入了hello数据,然后world由于时间片被抢,所以把world重新赋值给了hello位置

代码使用了Join方法,确保在主线程之前执行线程a和线程b

 

如何使线程变得安全?

我们使用synchronized对临界资源上锁,在代码块里执行操作

 

synchronized(临界资源对象){ // 对临界资源对象加锁

     // 代码(原子操作)

}

注:每个对象都有一个互斥锁标记,用来分配给线程的

只有拥有对象互斥锁标记的线程,才能进入该对象加锁的同步代码块中

线程退出同步代码块时,会释放相应的互斥锁标记

 

注意同步代码块 可以修改为 同步方法

这里我们把在run方法里面的代码抽取出来形成一个新的sell()方法,并在方法名前加了synchronized同步

注意:这个同步方法锁的对象就是this,当前的类的对象ticket

改一下:在方法前面加一个static,请问现在的锁是谁???  答案:是Ticket.class

这个和上面静态的 同步方法等价

 

小结:如果是非静态方法,锁就是当前this对象。如果是静态方法,锁就是当前的类

 

同步规则:

能不加锁就不加,加锁会导致程序的效率降低

 

已知JDK中线程安全的类,均为synchronized修饰的同步方法:

  • stringBuffer
  • Vector
  • Hashtable

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你在狗叫什么、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值