1: synchronized 可以同步方法(包括静态方法),也可以同步语句,甚至变量(对象引用,实例变量)
2:每个对象都有且只有一个锁,无论synchronized是针对对象还是方法,它取得的都是锁对象,并且锁对象(即同步方法或同步变量)可能被其它线程的对象访问,这是十分危险的,在设计多线程程序时应注意synchronized的使用,下面通过一个示例简要说明锁对象使用不当而被其它线程访问后引起的混乱。
public class ThreadDemo extends Thread{
int sum = 0;
public void run(){
for(int i = 0; i < 10; i ++){
showMessage();
System.out.print(System.currentTimeMillis() + "/n");
}
}
synchronized void showMessage(){
try{
Thread.sleep(1000);
}
catch(InterruptedException e){
e.printStackTrace();
}
sum += 1;
System.out.print(getName() + " : "+ sum + " ");
//............................
}
public static void main(String[] args){
Thread ob1 = new ThreadDemo()
Thread ob2 = new ThreadDemo();
ob1.start();
ob2.start();
}
}
运行结果如下:
Thread-0 : 1 1189866544054
Thread-1 : 1 1189866544054
Thread-0 : 2 1189866545056
Thread-1 : 2 1189866545056
Thread-0 : 3 1189866546057
Thread-1 : 3 1189866546057
Thread-0 : 4 1189866547058
Thread-1 : 4 1189866547058
Thread-0 : 5 1189866548060
Thread-1 : 5 1189866548060
Thread-0 : 6 1189866549061
Thread-1 : 6 1189866549061
Thread-0 : 7 1189866550063
Thread-1 : 7 1189866550063
Thread-0 : 8 1189866551064
Thread-1 : 8 1189866551064
Thread-0 : 9 1189866552066
Thread-1 : 9 1189866552066
Thread-0 : 10 1189866553067
Thread-1 : 10 1189866553067
从上述运行结果来看,synchronized并未起作用,当前线程的同步方法被另一个线程进入了,这是因为锁是针对对象的,锁是对象级的,在程序中,有两个对象ob1,ob2, ob1的同步方法可以被ob2调用,因为这两对象之间没有互斥,只有ob1在不同的线程间执行同步方法,才能形成互斥。上面的程序可以声明sum为static类型(参考文章java 关键字volatile ),正确的运行结果如下:
Thread-0 : 1 1189867573655
Thread-1 : 2 1189867573655
Thread-0 : 3 1189867574656
Thread-1 : 4 1189867574656
Thread-0 : 5 1189867575647
Thread-1 : 6 1189867575657
Thread-0 : 7 1189867576649
Thread-1 : 8 1189867576649
Thread-0 : 9 1189867577650
Thread-1 : 10 1189867577650
Thread-0 : 11 1189867578852
Thread-1 : 12 1189867578862
Thread-0 : 13 1189867579854
Thread-1 : 14 1189867579854
Thread-0 : 15 1189867580855
Thread-1 : 16 1189867580855
Thread-0 : 17 1189867581856
Thread-1 : 18 1189867581856
3:在避免2中所示的混乱后,synchronized可以对象
public void showMessage(){
synchronized(simpleObj){
...........................
}
}
锁就是simpleObj这个对象,可以使用一个简单的类型来代表这个锁,比如simpleObj = new String("")
3: 同步static方法
class staticDemo{
public static synchronized void a(){
}
public void b(){
synchronized(staticDemo.class){
}
}
}
在上述情况下,一个对象的多线程分别访问a()和b()两个方法时,是不会形成互斥的,因为它们不是同一个对象锁,a是obj对象,b是obj所属的那个class.
4:在线程间通信的有两个重要的方法wait()和notify(), 这两个方法一定要在synchronized块中,否则程序会throw “IllegalMonitorStateException”,但有synchronized的地方不一定有这两个方法。
5: 重要提示:在设计多线程程序的过程中,一定要首先明确synchronized锁定的确切对象。