核心思想:
java中的任何对象都是一把锁,有且只有一把钥匙。多个线程必须共享同一把锁才能互斥。普通方法的锁是当前对象this,静态方法的锁跟当前对象没有关系,它的锁是该类的类类型*.class。
public class TestSychoronized {
static Hashtable<String,String> a = new Hashtable<>();
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
A a = new A();
B b = new B(a);
C c = new C(a);
service.submit(b);
service.submit(c);
service.shutdown();
}
}
class A {
static int i=0;
public synchronized void f1() throws InterruptedException{
TimeUnit.SECONDS.sleep(5);
i++;
System.out.println(Thread.currentThread()+":f1-------:"+i);
};
public synchronized void f2() throws InterruptedException{
TimeUnit.SECONDS.sleep(5);
i++;
System.out.println(Thread.currentThread()+":f2-------:"+i);
};
public static synchronized void f3() throws InterruptedException{
TimeUnit.SECONDS.sleep(5);
i++;
System.out.println(Thread.currentThread()+":f3-------:"+i);
};
public static synchronized void f4() throws InterruptedException{
TimeUnit.SECONDS.sleep(5);
i++;
System.out.println(Thread.currentThread()+":f4-------:"+i);
};
}
class B implements Runnable{
private A a;
public B(A a) {
this.a = a;
}
@Override
public void run() {
try {
System.out.println(a.hashCode());
//a.f1();
//A.f2();
A.f3();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class C implements Runnable{
private A a;
public C(A a) {
this.a = a;
}
@Override
public void run() {
try {
System.out.println(a.hashCode());
//a.f1();
//a.f2();
//A.f3();
A.f4();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
上面代码可以模拟this锁 相同普通方法f1()的竞争过程(存在竞争),不同普通方法f1()与f2()的竞争过程(存在竞争);普通方法f1()和静态方法f3()是否存在竞争关系(不存在,一个加锁的是当前对象this,一个加锁的对象是类对象A.class),不同静态方法f3()和f4()的竞争关系(存在竞争,加的都是类锁A.class).
引申: Hashtable就利用的前两种情况, 当前线程做put写操作的时候,其他线程不能做读写操作, 当前线程做get读操作的时候其他线程也不能做读操作, 效率极低, 所以现在在多线程中已经几乎不用Hashtable了, 使用ConcurrentHashMap,锁分段技术,也可以进行改造,利用ReetrantReadWriteLock读写锁来改造HashMap,可以参考前边写的一篇文章:点击打开链接。