多线程中的线程安全问题

多线程的一些知识点,其中涉及到了一个不可忽视的问题,那就是多个线程在同时运行的时候,极易造成数据的错乱或丢失,这就是多线程的不安全问题,Java中为了解决这个问题,提供了三种主要的解决办法。

本博客就是为了记录下这个知识点,达到加深印象和方便回看的目的。

下面是我简单的总结。

方法一.同步代码块

简单理解就是,被同步代码块括住的内容,在多线程执行时会进行排队操作。(通过传一个锁的对象,初始为开放状态,当一个线程执行该任务时,会先检查这个锁对象,若未上锁,则线程执行任务,在一个线程执行任务时锁对象会上锁(通过底层的原理对锁对象进行标记),其他线程检查锁对象时发现是上锁状态,就会排队等待执行,期间不断监察锁对象,一旦解锁,继续抢占执行权)。

(1)格式:Synchronized(锁对象){

                          ##中间是任务的具体代码##

                    }

注:锁对象可以是任意对象,且多线程执行时检查的锁必须是同一把锁,可以将锁对象设置成一个任务类中的一个私有属性,这样在只有一个任务的情况下就只有一把锁。

方法二.同步方法

创建任务类时会重写run方法来定义任务,run方法内部就是任务本身的具体代码,同步方法就是将这些任务代码额外抽成另一个方法,用Synchronized修饰成同步方法,代表这是需要排队执行的任务,然后在run方法内部直接调用这个方法即可。

同步方法同样是利用锁标记来进行上锁解锁实现排队,这里需要注意:

           (1).如果抽成的方法是静态方法,锁对象就是任务类本身,即    任务类.class    。

           (2).如果不是静态方法,锁对象就是任务类创建的对象,一个任务就是一把锁。

               注: 【如果同时创建多个任务对象去多线程执行,就具有多个锁,是无意义的】

方法三.显式锁

之前的同步代码块和同步方法均为隐式锁,也就是你只需要传入一个锁对象,上锁解锁由底层执行。

接下来所说的显式锁,意思是自己定义锁对象,自己执行上锁和解锁操作。

需要用到一个类:Lock

注,自行定义锁对象依然是在任务类内部,绝对要保证只有一把锁。

(1).定义的方法是:

                         Lock   L = new ReentrantLock();   

          这就代表利用Lock类创建了一个锁对象。

(2).然后在任务类重写的run方法内部任务的开头,执行上锁操作(L.lock),代表的是如果一个线程进来了,要先执行上锁,这样其他线程就不可以使用了。

(3).在任务最后,执行解锁操作(L.unlock),重新开放任务的执行权。

显式锁有趣的一点是,它具有公平锁和不公平锁的概念。

(1).公平锁:在上锁的情况下,下一个排队的是谁,谁就是下一个执行任务的线程,不会存在所有线程抢夺谁抢到是谁的情况。

(2).不公平锁:谁抢到就是谁的(简单粗暴)。

至于对公平锁与不公平锁的设置,只需在创建锁对象时,括号内部传入一个Boolean值即可,True代表是公平锁,False代表是不公平锁。

例如:     

             Lock L = new ReentrantLock(True);

这就是一个公平锁。

对于多线程同时执行时的不安全问题,可通过上述三种方法解决,时刻要记住只能拥有一把锁的原则。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值