1.synchronized同步代码块
?? synchronized(obj){
????????? .....
???????? //同步代码块的代码
?? }
直接对obj对象同步监听,任何线程在修改指定的资源之前,首先对该资源加锁,在加锁期间其他线程无法修改该资源。
2.synchronized同步方法
? 1)类里的对象可以被多线程安全访问
?
class="java">public synchronized void draw(double drawAmount){ if (this.balance >= drawAmount) { System.out.println(Thread.currentThread().getName() + "取钱成功!吐出现金:" + drawAmount); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } this.balance = this.balance - drawAmount; System.out.println("\t余额为:" + balance); } else { System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足!"); } }
?总结:
?
??? 1)synchronized可修饰方法,可修饰代码块,但不能修饰构造器,属性。
??? 2)不要对线程安全的所有方法都进行同步。
3.同步锁(Lock)
?? 显式加锁,显式解锁
?? ReentrantLock(可重入锁):一个线程可以对已被加锁的ReentrantLock锁再次加锁,ReentrantLock对象会维持一个计数器来追踪lock()方法的嵌套调用。
??
public class Account { private final ReentrantLock lock = new ReentrantLock(); public void draw(double drawAmount) { //上锁 lock.lock(); try { ......//操作代码 } finally { //解锁 lock.unlock(); } } }
?
?? 4.死锁问题
???? 当两个线程互相等待对方释放同步监视器时就会发生死锁,当陷入死锁,所有线程处于阻塞状态,无法继续。
??? 四个必要条件:
??? 1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。 ??? 2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。 ??? 3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。 ??? 4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。 ??? 传统的线程通信: ?????? wait():导致当前线程等待 ?????? notify():唤醒等待线程中的单个线程 ?????? notifyAll():唤醒等待线程中的所有线程public class Account { private String accountNo; private double balance; private boolean flag = false; public Account(String accountNo, double balance) { this.accountNo = accountNo; this.balance = balance; } public int hashCode() { return accountNo.hashCode(); } public boolean equals(Object object) { if (this == object) { return true; } if (object != null && object.getClass() == this.getClass()) { Account account = (Account) object; return account.getAccountNo().equals(account); } return false; } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } public double getBalance() { return balance; } public synchronized void draw(double drawAmount) { try { if (!flag) { wait(); } else { if (this.balance >= drawAmount) { System.out.println(Thread.currentThread().getName() + "取钱成功!吐出现金:" + drawAmount); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } this.balance = this.balance - drawAmount; System.out.println("\t余额为:" + balance); flag = false; notifyAll(); } else { System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足!"); } } } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void deposit(double depositAmount) { try { if (flag) { wait(); } else { System.out.println(Thread.currentThread().getName() + "存款:" + depositAmount); balance += depositAmount; System.out.println("\t余额为:" + balance); flag = true; notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } } }? ??? 使用Condition类控制线程通信 ??? Condition实例的方法: ?????? await():类似于隐式同步监视器上的wait()方法 ?????? signal():类似于notify()方法 ?????? signalAll():类似于notifyAll()方法
public class Account { private String accountNo; private double balance; private boolean flag = false; private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); public Account(String accountNo, double balance) { this.accountNo = accountNo; this.balance = balance; } public int hashCode() { return accountNo.hashCode(); } public boolean equals(Object object) { if (this == object) { return true; } if (object != null && object.getClass() == this.getClass()) { Account account = (Account) object; return account.getAccountNo().equals(account); } return false; } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } public double getBalance() { return balance; } public void draw(double drawAmount) { lock.lock(); try { if (!flag) { condition.await(); } else { if (this.balance >= drawAmount) { System.out.println(Thread.currentThread().getName() + "取钱成功!吐出现金:" + drawAmount); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } this.balance = this.balance - drawAmount; System.out.println("\t余额为:" + balance); flag = false; condition.signalAll(); } else { System.out.println(Thread.currentThread().getName() + "取钱失败,余额不足!"); } } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public synchronized void deposit(double depositAmount) { lock.lock(); try { if (flag) { condition.await(); } else { System.out.println(Thread.currentThread().getName() + "存款:" + depositAmount); balance += depositAmount; System.out.println("\t余额为:" + balance); flag = true; condition.signalAll(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }??? 显式和隐式线程通信