java学习日记15,线程的同步机制

线程安全

例如,有一百张票要通过三个窗口卖出,由于CPU的执行权的分配是随机的,也就是三个窗口哪个窗口处于卖票执行流程是不确定的,假如一号窗口发现还有票,正要出票但还未出时,轮到了二号窗口执行,也要出票,就会发现两个窗口卖了同一个号码的票,也就是重票,或者还有一张票时,在一号窗口执行完正要出票时,轮到了二号三号窗口执行,就会发现卖出了已经不存在的票,也就是错票。
当多个线程执行过程中存在共享数据,也就是多个线程会对同一个数据进行操作时,就产生了线程安全问题。这三个窗口就是三个线程,而这100张票就是共享数据。
为了解决线程安全问题,显然,我们应该在其中一个线程操作共享数据时,禁止其它的线程对这个共享数据进行操作,就好像在一个线程操作这个共享数据时,就上一把锁,不允许其他线程进入这个共享数据的执行流程。

同步代码块

同步机制之一:
形式

  • synchronized(同步监视器){
    //需要被同步的代码
  • }
    需要被同步的代码也就是各个线程操作共享数据的代码。
    同步监视器可以由任何一个类的对象充当,只需要这些线程用的是同一个对象。
    在实现Runnable接口创建多线程的方式中,我们可以考虑使用this(当前对象)充当同步监视器。
    在继承Thread类创建多线程的方式中,慎用this充当同步监视器,考虑使用类.class(当前类)充当同步监视器。

同步方法

同步机制之二:
如果操作共享数据的代码可以完整的放在一个方法中,那我们不妨将这个方法声明为同步方法,也就是在方法的返回值类型前加上synchronized。
同步方法中虽然没有显式的声明同步监视器,但仍然存在同步监视器。
对于非静态的同步方法,同步监视器的是this(当前对象),而对于静态方法,同步监视器的是类.class(当前类)。

Lock锁

同步机制之三:
形式:
private ReentrantLock lock=new ReentrantLock();
try{
lock.lock();
//需要被同步的代码
}finally{
lock.unlock();
}
对于synchronized机制,在执行完同步代码块后会自动的释放同步监视器,而Lock则需要手动的启动同步(lock),手动的结束(unlock),并且,Lock可以通过tryLock()判断锁的状态。

死锁

不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。
一个线程需要同步资源A和同步资源B,另一个线程需要同步资源B和同步资源A;顺利的情况是,第一个线程先执行完毕,释放了同步资源B 和A,这样另一个线程就可以拿到同步资源,顺利执行。
但是,如果第一个线程拿到了同步资源A,在等待同步资源B时,另一个线程刚好拿到同步资源B,在等待同步资源A,这时就形成了死锁,两个线程都无法继续执行。
死锁的状态是我们必须避免的,主要的方式有:
1)专门的算法、原则
2)尽量减少同步资源的定义
3)尽量避免嵌套同步

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值