线程的同步,除了同步方法外,我们还可以使用代码块,使用代码块比同步方法有更好的效果。。
追其同步的根本目的,是控制竞争资源的正确访问,因此只要在访问竞争资源的时候,只要保证同一时刻只能有一个线程访问即可,因此Java引入了同步代码块的策略,以提高其性能。我们对上一篇文章进行改进:
User类:
package thread_synchronization;
public class User {
private String code;//账号
private int cash;//金额
public User(String code,int cash){
this.code=code;
this.cash=cash;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public int getCash() {
return cash;
}
public void setCash(int cash) {
this.cash = cash;
}
/**
* (1)、使用synchronized代码块
* (2)、计算剩余额度
* (3)、使用synchronized锁定线程对象,实现线程同步,从而保证计算结果的正确性,如果去掉synchronized,数据会发生错误,是错误的
* @param x
*/
public void oper(int x){
try {
Thread.sleep(10L);
synchronized (this){
this.cash+=x;
System.out.println(Thread.currentThread().getName()+"运行结束,增加"+x+","+"当前余额剩余为:"+cash);
}
Thread.sleep(10L);
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public String toString() {
return "User{" + "code='" + code + '\'' + ",cash=" + cash + '}';
}
}
ThreadExtend_Synchronization类
public class ThreadExtend_Synchronization extends Thread{
private User user;
private int y;
ThreadExtend_Synchronization(String name, User user, int y){
super(name);
this.user=user;
this.y=y;
}
@Override
public void run() {
user.oper(y);
}
public static void main(String args[]){
User user=new User("张三",100);
Thread thread1=new ThreadExtend_Synchronization("线程A",user,1);
Thread thread2=new ThreadExtend_Synchronization("线程B",user,2);
Thread thread3=new ThreadExtend_Synchronization("线程C",user,3);
Thread thread4=new ThreadExtend_Synchronization("线程D",user,4);
Thread thread5=new ThreadExtend_Synchronization("线程E",user,-10);
Thread thread6=new ThreadExtend_Synchronization("线程F",user,-20);
Thread thread7=new ThreadExtend_Synchronization("线程G",user,-30);
Thread thread8=new ThreadExtend_Synchronization("线程H",user,-40);
Thread thread9=new ThreadExtend_Synchronization("线程I",user,-50);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread6.start();
thread7.start();
thread8.start();
thread9.start();
}
}
运行结果如下:
线程C运行结束,增加3,当前余额剩余为:103
线程B运行结束,增加2,当前余额剩余为:105
线程A运行结束,增加1,当前余额剩余为:106
线程D运行结束,增加4,当前余额剩余为:110
线程E运行结束,增加-10,当前余额剩余为:100
线程H运行结束,增加-40,当前余额剩余为:60
线程F运行结束,增加-20,当前余额剩余为:40
线程G运行结束,增加-30,当前余额剩余为:10
线程I运行结束,增加-50,当前余额剩余为:-40
注意:使用synchronized关键字的时候,应该尽可能的避免在synchronized方法或者在synchronized块当中使用sleep或者yield方法,因为synchronized占用着对象锁,使用了sleep()方法以后,只能等待着它醒来以后,其它线程才能执行,这样的话严重影响了效率,也不符合逻辑。
线程同步小结:
1、线程同步的目的是多个线程访问一个资源造成对资源的破坏。
2、线程同步的方法是通过锁来实现,每个对象都有且仅有一个锁,线程一旦获得了对象锁,那么其访问该对象的线程就无法再访问该对象的其它线程。
3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象,静态和非静态方法的锁互不干预。
4、对于同步,要时刻清醒在哪个对象上进行同步,这是关键。
5、当多个线程等待一个对象锁的时候,没有获得锁的线程将发生阻塞。
6、死锁是线程间相互等待锁造成的,在实际应用当中发生的机率很小。