Synchronized和Static Synchronized区别
通过分析这两个用法的分析,我们可以理解java中锁的概念。一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全局锁(该锁针对的是类,无论实例多少个对象,那么线程都共享该锁)。实例锁对应的就是synchronized关键字,而类锁(全局锁)对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。下面的文章做了很好的总结:
1.synchronized与static synchronized 的区别
synchronized是对类的当前实例(当前对象)进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是“类的当前实例”, 类的两个不同实例就没有这种约束了。
那么static synchronized恰好就是要控制类的所有实例的并发访问,static synchronized是限制多线程中该类的所有实例同时访问jvm中该类所对应的代码块。实际上,在类中如果某方法或某代码块中有 synchronized,那么在生成一个该类实例后,该实例也就有一个监视块,防止线程并发访问该实例的synchronized保护块,而static synchronized则是所有该类的所有实例公用得一个监视块,这就是他们两个的区别。也就是说synchronized相当于 this.synchronized,而static synchronized相当于Something.synchronized.(后面又讲解)
一个日本作者-结成浩的《java多线程设计模式》有这样的一个列子:
[java] view plaincopy
-
pulbic class Something(){
-
public synchronized void isSyncA(){}
-
public synchronized void isSyncB(){}
-
public static synchronized void cSyncA(){}
-
public static synchronized void cSyncB(){}
-
}
那么,假如有Something类的两个实例x与y,那么下列各组方法被多线程同时访问的情况是怎样的?
[java] view plaincopy
-
a. x.isSyncA()与x.isSyncB()
-
b. x.isSyncA()与y.isSyncA()
-
c. x.cSyncA()与y.cSyncB()
-
d. x.isSyncA()与Something.cSyncA()
这里,很清楚的可以判断:
a,都是对同一个实例(x)的synchronized域访问,因此不能被同时访问。(多线程中访问x的不同synchronized域不能同时访问)
如果在多个线程中访问x.isSyncA(),因为仍然是对同一个实例,且对同一个方法加锁,所以多个线程中也不能同时访问。(多线程中访问x的同一个synchronized域不能同时访问)
b,是针对不同实例的,因此可以同时被访问(对象锁对于不同的对象实例没有锁的约束)
c,因为是static synchronized,所以不同实例之间仍然会被限制,相当于Something.isSyncA()与 Something.isSyncB()了,因此不能被同时访问。
那么,第d呢?,书上的 答案是可以被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同的原因。
个人分析也就是synchronized 与static synchronized 相当于两帮派,各自管各自,相互之间就无约束了,可以被同时访问。
举个例子:
Java代码
-
public class TestSynchronized
-
{
-
public synchronized void test1()
-
{
-
int i = 5;
-
while( i-- > 0)
-
{
-
System.out.println(Thread.currentThread().getName() + " : " + i);
-
try
-
{
-
Thread.sleep(500);
-
}
-
catch (InterruptedException ie)
-
{
-
}
-
}
-
}
-
-
public static synchronized void test2()
-
{
-
int i = 5;