[size=large] 线程是很久以前学习的东西了,现在看来已经有很多都遗忘了,但最近因为线程同步的问题发现了synchronized关键字,synchronized关键字以前也看到过,但是没有系统详细的学习过,这次查了点资料、看了些视频,就来讲述一下我对synchronized关键字的理解。
java语言对于多线程的支持与同步机制收到大家的喜爱,但是多线程机制肯定会牵扯到对类成员变量的访问与方法的使用,因为线程是抢占式的,也就是说并没有顺序可言,谁占用了资源,谁就可以运行,这时就用到了synchronized关键字。
synchronized 方法控制对类成员变量的访问:每个对象对应一把锁,每个 synchronized 方法都必须获得调用该方法的对象的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个对象,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态,从而有效避免了类成员变量的访问冲突。由此,我们可以猜想一下,一些回合制的线程游戏原则上也可以应用synchronized关键字。
现在我们就用一些代码来实际讲述一下:[/size]
[size=large] 程序中共有两个线程运行,如果没有synchronized的话,运行结果肯定是乱序的,但是在execute方法中加了synchronized之后就给对象加了锁,只有在t1线程运行完之后才让t2运行。
但是如果将synchronized加在两个不同的对象中,而两个对象各自有一个线程的话,这两个线程不会相互影响,因为只有同一个对象的线程才会由synchronized关键字加锁而产生排斥进而产生先后顺序。
当然,synchronized关键字也有缺点:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。
最后就来讲一下synchronized关键字与static synchronized关键字的区别。synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是“类的当前实例”, 类的两个不同实例就没有这种约束了。那么static synchronized恰好就是要控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例同时访问对应的代码快。如果有两个对象分别用static synchronized和synchronized关键字加锁的话,因为加锁的对象不同,所以也就不会相互影响。而如果两个都是static synchronized的话就会先后执行。[/size]
java语言对于多线程的支持与同步机制收到大家的喜爱,但是多线程机制肯定会牵扯到对类成员变量的访问与方法的使用,因为线程是抢占式的,也就是说并没有顺序可言,谁占用了资源,谁就可以运行,这时就用到了synchronized关键字。
synchronized 方法控制对类成员变量的访问:每个对象对应一把锁,每个 synchronized 方法都必须获得调用该方法的对象的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个对象,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态,从而有效避免了类成员变量的访问冲突。由此,我们可以猜想一下,一些回合制的线程游戏原则上也可以应用synchronized关键字。
现在我们就用一些代码来实际讲述一下:[/size]
public class ThreadTest4 {
public static void main(String [] args){
Example example=new Example();
Thread t1=new TheThread(example);
Thread t2=new TheThread(example);
t1.start();
t2.start();
}
}
class Example{
public synchronized void execute(){
for(int i=0;i<50;i++){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("example:"+i);
}
}
}
class TheThread extends Thread{
private Example example;
public TheThread(Example example){
this.example=example;
}
public void run(){
this.example.execute();
}
}}
[size=large] 程序中共有两个线程运行,如果没有synchronized的话,运行结果肯定是乱序的,但是在execute方法中加了synchronized之后就给对象加了锁,只有在t1线程运行完之后才让t2运行。
但是如果将synchronized加在两个不同的对象中,而两个对象各自有一个线程的话,这两个线程不会相互影响,因为只有同一个对象的线程才会由synchronized关键字加锁而产生排斥进而产生先后顺序。
当然,synchronized关键字也有缺点:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。
最后就来讲一下synchronized关键字与static synchronized关键字的区别。synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是“类的当前实例”, 类的两个不同实例就没有这种约束了。那么static synchronized恰好就是要控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例同时访问对应的代码快。如果有两个对象分别用static synchronized和synchronized关键字加锁的话,因为加锁的对象不同,所以也就不会相互影响。而如果两个都是static synchronized的话就会先后执行。[/size]