//synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法//每个对象只有一个锁(lock)与之相关联。//实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。/**//*无论synchronized关键字加在方法上还是对象上,它取得的锁都是锁在了对象上,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。每个对象只有一个锁(lock)与之相关联。实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。还有一些技巧可以让我们对共享资源的同步访问更加安全:定义private 的instance变量+它的 get方法,而不要定义public/protected的instance变量。如果将变量定义为public,对象在外界可以绕过同步方法的控制而直接取得它,并改动它。如果instance变量是一个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。 这个时候就需要将get方法也加上synchronized同步,并且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了。*//**//*Wait时别的线程可以访问锁定对象调用wait方法的时候必需锁定该对象Object提供的方法Sleep时别的线程也不可以访问锁定对象Thread提供的方法*/public class TestSync implements Runnable ...{ Timer timer = new Timer(); public static void main(String[] args) ...{ TestSync test = new TestSync(); Thread t1 = new Thread(test); Thread t2 = new Thread(test); t1.setName("t1"); t2.setName("t2"); t1.start(); t2.start(); //new Foo().methodBBB(); } public void run()...{ timer.add(Thread.currentThread().getName()); }}class Timer...{ private int num = 0; String s = "123"; public void add(String name)...{ synchronized (s) ...{ // this只当前Timer对象 num ++; try ...{Thread.sleep(1);} catch (InterruptedException e) ...{} System.out.println(name+", 你是第"+num+"个使用timer的线程"); } } public int readNum() ...{ return num; }}///////////////////////////////////////////////////////////////////////////////////////////////////////////第一种情况//修饰方法//这也就是同步方法,那这时synchronized锁定的是哪个对象呢?//它锁定的是调用这个同步方法对象。//也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。//但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。//////////////////////////////////////////////////////////////////////////////////////////////////////**//*Public synchronized void methodAAA(){ //……}*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////第二种情况//当有一个明确的对象作为锁时,就可以这样对so这个对象加锁,谁拿到这个锁谁就可以运行它所控制的那段代码/**//*public void method3(SomeObject so){ synchronized(so){ //…… }}*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////第三种情况//但当没有明确的对象作为锁,只是想让一段代码同步时,//可以创建一个特殊的instance变量(它得是一个对象)来充当锁://注:零长度的byte数组对象创建起来将比任何对象都经济//查看编译后的字节码://生成零长度的byte[]对象只需3条操作码,//而Object lock = new Object()则需要7行操作码。/**//*class Foo implements Runnable{ private byte[] lock = new byte[0]; // 特殊的instance变量 Public void methodA(){ synchronized(lock) { //…… } } //……}*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////第四种情况//将synchronized作用于static 函数,示例代码如下//代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,//取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。//------>下面的说法可能有问题!//如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized 的instance函数B,//那么这个类的同一对象Obj在多线程中分别访问A和B两个方法时,不会构成同步,//因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。 /**//*class Foo { public synchronized static void methodAAA(){ // 同步的static 函数 try {Thread.sleep(1000);}catch (InterruptedException e) {} System.out.println("methodAAA......"); } public void methodBBB(){ synchronized(Foo.class){ // class literal(类名称字面常量) } System.out.println(Foo.class.getName() + ".class"); }}*/////////////////////////////////////////////////////////////////////////////////////////////////////补充: class Foo ...{ static Foo foo = new Foo(); // 同步的static 函数 public synchronized static void methodAAA()...{ System.out.println("methodAAA......"); try ...{ Thread.sleep(5000); }catch (InterruptedException e) ...{ } } // 同步Foo.class.....说明:class literal(类名称字面常量) public void methodBBB()...{ synchronized(Foo.class)...{ System.out.println(Foo.class.getName() + ".class"); try ...{ Thread.sleep(5000); }catch (InterruptedException e) ...{ } } } //普通方法 public void methodCCC()...{ System.out.println("generic method ......"); try ...{ Thread.sleep(5000); }catch (InterruptedException e) ...{ } }}class TestFoo...{ public static void main(String [] args)...{ //通过不同的实例调用methodAAA //new Thread(new A()).start(); //new Thread(new A()).start(); //通过不同的实例调用methodBBB //new Thread(new B()).start(); //new Thread(new B()).start(); //通过不同的实例调用methodAAA和methodBBB //new Thread(new A()).start(); //new Thread(new B()).start(); //通过相同的实例调用methodAAA //new Thread(new AA()).start(); //new Thread(new AA()).start(); //通过相同的实例调用methodBBB //new Thread(new BB()).start(); //new Thread(new BB()).start(); //通过相同的实例调用methodAAA和methodBBB //new Thread(new AA()).start(); //new Thread(new BB()).start(); //调用普通方法 //Foo.foo.methodCCC(); }}class A implements Runnable ...{ public void run() ...{ new Foo().methodAAA(); }}class B implements Runnable ...{ public void run() ...{ new Foo().methodBBB(); }}class AA implements Runnable ...{ public void run() ...{ Foo.foo.methodAAA(); }}class BB implements Runnable ...{ public void run() ...{ Foo.foo.methodBBB(); }}