synchronized:对像的当前实例进行加锁,防止其他线程同时访问该类实例的所有synchronized块。
synchronized static:是限制线程同时访问jvm中该类的所有实例同时访问对应的代码块,且该类的所有代码块共用一把锁。
- pulbic class syncMethod(){
-
- public synchronized void syncA(){}
-
- public synchronized void syncB(){}
-
- public static synchronized void staticA(){}
-
- public static synchronized void staticB(){}
-
- }
假设上面的类有四个方法,然后有两个实例a,b调用,那么哪些可以同时被访问呢?
1、a.syncA() 和 a.syncB()。
2、a.syncA() 和 b.syncB()。
3、a.staticA() 和 b.staticB()。
4、a.staticA() 和 syncMethod.staticB()。
这里我们可以根据上面两个定律判断:
1、这个肯定是可以加锁成功,两个线程不能同时访问。
2、这个肯定加锁失败,两个线程可以同时访问。
3、这个因为是静态,而且是不同的实例,根据定律也是可以加锁成功,两个线程不能同时访问。
4、这里因为一个是实例方法锁,一个是类方法锁,锁的对象不同,所以可以被同时访问。
对象锁只对当前对象进行加锁,锁this和synchronized普通方法一样,只对调用的实例进行加锁,而锁.class是指对类加锁。
synchornized(this)
- public class Sync823 {
-
- public static void main(String[] args) {
- Service823 service823 = new Service823();
- ThreadA823 threadA823 = new ThreadA823(service823);
- threadA823.setName("鸣人");
- threadA823.start();
-
- Service823 service82311 = new Service823();
- ThreadB823 threadB823 = new ThreadB823(service823);
- threadB823.setName("佐助");
- threadB823.start();
- }
-
- }
-
- class Service823{
-
- void thread823(){
- synchronized (this){
- for (int i = 0; i < 100; i++) {
- if(Thread.currentThread().getName().equals("鸣人")){
- System.out.println("鸣人释放 螺旋丸");
- continue;
- }
- System.out.println("佐助释放 千鸟");
- }
- }
- }
- }
-
- class ThreadA823 extends Thread{
-
- private Service823 service823;
-
- ThreadA823(Service823 service823){
- this.service823 = service823;
- }
-
- @Override
- public void run() {
- service823.thread823();
- }
- }
-
- class ThreadB823 extends Thread{
-
- private Service823 service823;
-
- ThreadB823(Service823 service823){
- this.service823 = service823;
- }
-
- @Override
- public void run() {
- service823.thread823();
- }
- }
-
-
-
-
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 佐助释放 千鸟
- 佐助释放 千鸟
- 佐助释放 千鸟
- 佐助释放 千鸟
- 佐助释放 千鸟
从上面代码可以看到,当锁this的时候,当是同一个实例,这时候是上锁成功,两个线程不会同时访问,和前面的synchronized修饰普通方法一样,但如果换成 不同的实例,则不会互斥。
- public static void main(String[] args) {
- Service823 service823 = new Service823();
- ThreadA823 threadA823 = new ThreadA823(service823);
- threadA823.setName("鸣人");
- threadA823.start();
-
- Service823 service82311 = new Service823();
- ThreadB823 threadB823 = new ThreadB823(service82311);
- threadB823.setName("佐助");
- threadB823.start();
- }
-
-
- 佐助释放 千鸟
- 佐助释放 千鸟
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 佐助释放 千鸟
- 佐助释放 千鸟
synchronized(.class)
- synchronized (Service823.class){
- for (int i = 0; i < 100; i++) {
- if(Thread.currentThread().getName().equals("鸣人")){
- System.out.println("鸣人释放 螺旋丸");
- continue;
- }
- System.out.println("佐助释放 千鸟");
- }
- }
-
-
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 鸣人释放 螺旋丸
- 佐助释放 千鸟
- 佐助释放 千鸟
- 佐助释放 千鸟
- 佐助释放 千鸟
这时候会发现,无论是创建几个实例,都会互斥成功,所以锁.class锁的是这个类,并不是实例。