线程同步

线程同步

为什么要实现同步?

java的多线程实现了并发控制,当多个线程同时处理同一个内存单元时,可能会引发错误,比如经典的问题—银行取钱问题,当多个用户同时进行取钱时可能会出现余额为负数的情况(如果没有实现同步)

实现同步的方法

1、同步代码块
由关键字synchronized修饰的代码块
语法格式:

synchronized(obj){
//此处的代码就是同步代码块
}
//上面语法格式中synchronized后括号里的obj就是同步监视器,线程开始执行代码块之前,必须先获得对同步监视器的锁定。
//注意任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放对该同步监视器的锁定。同步是一种高开销的操作,应该尽可能的减少同步的使用,对重要的代码块实现同步即可。

2、同步方法
由关键字synchronized修饰的方法

public synchronized void draw(){
}
//对于synchronized修饰的实例方法,无需显式指定同步监视器,同步方法的同步监视器是this
//注意:synchronized关键字可以修饰方法,可以修饰代码块,但不能修饰显式构造器,成员变量等。

3、同步锁Lock
Lock提供了比synchronized方法和synchronized代码块更广泛的锁定操作,Lock允许实现更灵活的结构,可以具有差别很大的属性,并且支持多个相关Condition对象
在实现线程安全的控制中,比较常用的是ReentrantLock(可重入锁),使用该对象可以显式的加锁,释放锁,通常使用ReentrantLock的代码如下:

 class X
 {
 //定义锁对象
 private final ReentrantLock lock=new ReentrantLock();
 //定义需要保证线程安全的方法
 public void m(){
 lock.lock();
 try
 {
 //需要保证线程安全的代码
 //...method body
 }
 finally{
 lock.unlock();
 }
 }
 }
//使用ReentrantLock 对象来进行同步,加锁和释放锁出现在不同的作用范围内时,通常建议使用finally块来保证在必要的时候释放锁。
//ReentrantLock锁具有可重用性,也就是说,一个线程可以对已被加锁的ReentrantLock锁再次加锁。ReentrantLock对象会维持一个计数器来跟踪lock()方法的嵌套调用,线程在每次调用lock()加锁后,必须显式调用unlock()来释放锁,所以一段被锁保护的代码可以调用另一个被相同锁保护的方法。
死锁

当两个线程相互等待对方释放同步监视器时会发生死锁,java虚拟机没有监测,也没有采取措施来处理死锁的情况,所以多线程编程时应该采取措施避免死锁出现。一旦出现死锁,整个程序既不会发生任何异常,也不会给出任何的提示,只是所有的线程处于阻塞状态,无法继续。
注意:由于Thread类的suspend()方法也很容易导致死锁,所以java不再推荐使用该方法来暂停线程的执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值