对于synchronized的运行顺序理解

一、synchronized

同步关键字,分为同步代码块和同步函数

二、对synchronized的理解(未加static关键字)(以下所说:对同步方法和同步代码块均适用)

对象的创建是以类为模板的

1、两个并发的线程访问同一个类Object中的synchronized(this)同步代码块或者同步方法时,同一时间只能执行一个,另一个必须要等待当前线程执行完才能执行(同一个对象:见下面的testSynchronized,分为两个线程,两个线程访问的是一个方法)(一个对象两个线程一个方法)

例子:

public class TestSynchronized {
    public void test1(){
        synchronized(this) {
            System.out.println("1"+this);
            int i = 5; 
             while( i-- > 0) {
                 System.out.println(Thread.currentThread().getName() + " : " + i);  
                 try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
             }
        }
    }
    public static void main(String[] args) {
        final TestSynchronized testSynchronized = new TestSynchronized();
        final TestSynchronized testSynchronized1 = new TestSynchronized();
        Thread thread1 = new Thread(new Runnable() {
            
            @Override
            public void run() {
                testSynchronized.test1();
            }
        },"test1");
        Thread thread3 = new Thread(new Runnable() {
            
            @Override
            public void run() {
                testSynchronized.test1();
            }
        },"test3");
        
        thread1.start();
        thread3.start();
    }
}

结果:

在这里插入图片描述

2、两个并发的线程访问同一个类Object中的synchronized(this)同步代码块或者同步方法时,两个交替进行,因为对象的创建是以类为模板的,所以两个对象都会有自己独立的方法(不同对象:testSynchronized和testSynchronized1,分为两个线程,两个线程访问的是一个方法)(两个对象两个线程一个方法)

例子:和第一个的例子相比仅仅修改了第31行

 public class TestSynchronized {
     public void test1(){
         synchronized(this) {
             System.out.println("1"+this);
             int i = 5; 
              while( i-- > 0) {
                  System.out.println(Thread.currentThread().getName() + " : " + i);  
                  try {
                     Thread.sleep(500);
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
              }
         }
     }
     public static void main(String[] args) {
         final TestSynchronized testSynchronized = new TestSynchronized();
         final TestSynchronized testSynchronized1 = new TestSynchronized();
         Thread thread1 = new Thread(new Runnable() {
             
             @Override
             public void run() {
                 testSynchronized.test1();
             }
         },"test1");
         Thread thread3 = new Thread(new Runnable() {
             
             @Override
             public void run() {
                 testSynchronized1.test1();
             }
         },"test3");
         thread1.start();
         thread3.start();
     }
 }

复制代码
  结果:

在这里插入图片描述

3、(两个线程同一对象)当一个线程已经访问了该类中的一个synchronized方法,另一个线程就不能再去访问访问其他的synchronized方法(对象锁是锁住了对象,所以只能执行完这个再去执行另一个)(一个对象两个线程两个方法)

例子:

 public class TestSynchronized {
     public void test1(){
         synchronized(this) {
             System.out.println("1"+this);
             int i = 5; 
              while( i-- > 0) {
                  System.out.println(Thread.currentThread().getName() + " : " + i);  
                  try {
                     Thread.sleep(500);
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
              }
         }
     }
     public synchronized void test2(){
         System.out.println(this);
         int i = 5; 
          while( i-- > 0) {
              System.out.println(Thread.currentThread().getName() + " : " + i);  
              try {
                 Thread.sleep(500);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
          }
     }
     public static void main(String[] args) {
         final TestSynchronized testSynchronized = new TestSynchronized();
         final TestSynchronized testSynchronized1 = new TestSynchronized();
         Thread thread1 = new Thread(new Runnable() {
             
             @Override
             public void run() {
                 testSynchronized.test1();
             }
         },"test1");
         Thread thread2 = new Thread(new Runnable() {
             
             @Override
             public void run() {
                 testSynchronized.test2();
             }
         },"test2");
         thread1.start();
         thread2.start();
     }
 }

结果:

在这里插入图片描述

4、(同一个对象)当一个线程已经访问了一个类的synchronized方法,那么另一个线程也可以访问其他的非synchronized方法,结果是交替进行的(一个对象两个线程两个方法[一个synchronized一个非synchronized的])

进行了同步的方法(加锁方法)和没有进行同步的方法(普通方法)是互不影响的,一个线程进入了同步方法,得到了对象锁,其他线程还是可以访问那些没有同步的方法(普通方法)

例子:

public class TestSynchronized {
     public void test1(){
         synchronized(this) {
             System.out.println("1"+this);
             int i = 5; 
              while( i-- > 0) {
                  System.out.println(Thread.currentThread().getName() + " : " + i);  
                  try {
                     Thread.sleep(500);
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
              }
         }
     }
         //非synchronized
     public void test2(){
         System.out.println(this);
         int i = 5; 
          while( i-- > 0) {
              System.out.println(Thread.currentThread().getName() + " : " + i);  
              try {
                 Thread.sleep(500);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
          }
     }
     public static void main(String[] args) {
         final TestSynchronized testSynchronized = new TestSynchronized();
         final TestSynchronized testSynchronized1 = new TestSynchronized();
         Thread thread1 = new Thread(new Runnable() {
             
             @Override
             public void run() {
                 testSynchronized.test1();
             }
         },"test1");
         Thread thread2 = new Thread(new Runnable() {
             
             @Override
             public void run() {
                 testSynchronized.test2();
             }
         },"test2");
         
         thread2.start();
         thread1.start();
     }
 }

结果:

在这里插入图片描述

三、加了static后现成的执行

1、对于一个类,一个线程访问了加了static的synchronized方法,另一个线程同样可以访问未加static的synchronized方法,所以结果是交替进行,因为类和对象不同(static修饰后锁住的是类,所有对象共享,而没有加static锁住的是对象,只有每个对象私有)(一个对象一个类两个线程两个方法)

例子:

  public class TestSynchronized {
     public void test1(){
         synchronized(this) {
             int i = 5; 
              while( i-- > 0) {
                  System.out.println(Thread.currentThread().getName() + " : " + i);  
                  try {
                     Thread.sleep(500);
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
              }
         }
     }
     public static synchronized void test2(){
         int i = 5; 
          while( i-- > 0) {
              System.out.println(Thread.currentThread().getName() + " : " + i);  
              try {
                 Thread.sleep(500);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
          }
     }
     public static void main(String[] args) {
         final TestSynchronized testSynchronized = new TestSynchronized();
         Thread thread1 = new Thread(new Runnable() {
             
             @Override
             public void run() {
          //对象调用的是该对象自己的方法
                 testSynchronized.test1();
             }
         },"test1");
         Thread thread2 = new Thread(new Runnable() {
             
             @Override
             public void run() {
         //类调用的是类方法
                 TestSynchronized.test2();
             }
         },"test2");
         thread2.start();
         thread1.start();
     }
 }

结果:
在这里插入图片描述

2、两个都是被static修饰的synchronized方法,结果是一个线程等待另一个线程执行完才会执行,因为类是一样的(和同一个对象的理解差不多),方法被synchronized修饰只能一个执行完再执行另一个(一个类两个线程两个方法)

例子:

 public class TestSynchronized {
     public static void test1(){
         synchronized(TestSynchronized.class) {
             int i = 5; 
              while( i-- > 0) {
                  System.out.println(Thread.currentThread().getName() + " : " + i);  
                  try {
                     Thread.sleep(500);
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
              }
         }
     }
     public static synchronized void test2(){
         int i = 5; 
          while( i-- > 0) {
              System.out.println(Thread.currentThread().getName() + " : " + i);  
              try {
                 Thread.sleep(500);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
          }
     }
     public static void main(String[] args) {
         final TestSynchronized testSynchronized = new TestSynchronized();
         Thread thread1 = new Thread(new Runnable() {
             
             @Override
             public void run() {
                 TestSynchronized.test1();
             }
         },"test1");
         Thread thread2 = new Thread(new Runnable() {
             
             @Override
             public void run() {
                 TestSynchronized.test2();
             }
         },"test2");
         
         thread2.start();
         thread1.start();
     }
 }

结果:

在这里插入图片描述

补充:
  面试的一道题:

一个只被synchronized修饰的方法fun(),现有两个对象a,b,分别是两个线程t1,t2

①a.fun()和b.fun()可以同时进行吗?

答:可以,因为是两个为不同的对象,对象的创建是以类为模板的,所以这两个对象中都会有自己的fun()方法,所以两个线程开启后会交替进行,如上面的二2

②回答完可以后,怎么可以让两个分开进行即一个完了之后再进行另一个?

答:给方法加上static关键字,static锁住了类,此时锁为“类锁”,所以虽然对象不一样但是类都是一样的,所以简单说就是一个类两个线程调用一个方法,肯定是一个执行完再执行另一个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值