1、被syncronized修饰的方法,是对类的对象加锁,也就是说,当对象访问该方法时,当前的对象会被加锁,同一时刻同一对象不能再访问该方法,或者该对象的其他被syncronized修饰的方法。不同对象,同一时刻可以访问同一个syncronized方法或其他syncronized方法,两个对象之间并不产生互斥关系。
2、被static、syncronized修饰的方法,是对类进行加锁,也就是说,同一时刻只有一个类能访问该方法。对象锁与类锁不会产生互斥关系。
如,Test 类有如下2个成员方法,被syncronized所修饰,
另有一个被syncronized所修饰的静态方法,
有 Test 类的两个实例, ta 和 tb ,则 ta 和 tb 分别同时拥有funA()、funB()成员方法。
那么上面一段话可以解释如下:
1、在同一时刻,当ta对象去访问funA()方法时,ta对象就被锁定了,这时候ta是不能再去访问funB()方法了;直到ta访问funA()方法结束并对ta的锁释放后,ta才能继续访问funB()方法。
2、当ta对象去访问funA()方法时,此时ta对象被锁定了;假如同一时刻tb对象也想去访问funA()方法,是能成功访问的,此时tb对象被锁定了。因为ta、tb是两个不同的对象,各自都拥有funA()、funB()方法,对两个对象分别加锁,并不会产生互斥关系。
3、当ta / tb访问funX()方法时,假如此时想访问Test类的funC()方法,是能访问成功的。这也就是对象锁与类锁并不会产生互斥的关系。
synchronized关键字可以锁class也可以锁对象。如果它修饰的是static方法那么他锁的是class,也就是多线程访问该class加载的任何实例的synchronized方法都会有阻塞问题。如果锁的是一般方法那么java默认锁的是当前实例也就是this.那么所有使用同一个对象的线程都会产生竞争。上述例子应该属于第二种。但是你这个写法看不出问题。因为t.start()方法是吧调用线程的权利交给了jvm。jvm使用线程争抢机制确定那个线程先来执行而已。而tt.m2();方法只能说明你主线程调用m2方法。m1和m2谁先执行其实也不能保证。所有最终的结果很难说明问题。