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();
}
}
}
??? 显式和隐式线程通信