zoukankan      html  css  js  c++  java
  • 对于synchronized的理解

    一、synchronized

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

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

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

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

         例子:

     1 public class TestSynchronized {
     2     public void test1(){
     3         synchronized(this) {
     4             System.out.println("1"+this);
     5             int i = 5; 
     6              while( i-- > 0) {
     7                  System.out.println(Thread.currentThread().getName() + " : " + i);  
     8                  try {
     9                     Thread.sleep(500);
    10                 } catch (InterruptedException e) {
    11                     // TODO Auto-generated catch block
    12                     e.printStackTrace();
    13                 }
    14              }
    15         }
    16     }
    17     public static void main(String[] args) {
    18         final TestSynchronized testSynchronized = new TestSynchronized();
    19         final TestSynchronized testSynchronized1 = new TestSynchronized();
    20         Thread thread1 = new Thread(new Runnable() {
    21             
    22             @Override
    23             public void run() {
    24                 testSynchronized.test1();
    25             }
    26         },"test1");
    27         Thread thread3 = new Thread(new Runnable() {
    28             
    29             @Override
    30             public void run() {
    31                 testSynchronized.test1();
    32             }
    33         },"test3");
    34         
    35         thread1.start();
    36         thread3.start();
    37     }
    38 }

    结果:

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

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

     1 public class TestSynchronized {
     2     public void test1(){
     3         synchronized(this) {
     4             System.out.println("1"+this);
     5             int i = 5; 
     6              while( i-- > 0) {
     7                  System.out.println(Thread.currentThread().getName() + " : " + i);  
     8                  try {
     9                     Thread.sleep(500);
    10                 } catch (InterruptedException e) {
    11                     // TODO Auto-generated catch block
    12                     e.printStackTrace();
    13                 }
    14              }
    15         }
    16     }
    17     public static void main(String[] args) {
    18         final TestSynchronized testSynchronized = new TestSynchronized();
    19         final TestSynchronized testSynchronized1 = new TestSynchronized();
    20         Thread thread1 = new Thread(new Runnable() {
    21             
    22             @Override
    23             public void run() {
    24                 testSynchronized.test1();
    25             }
    26         },"test1");
    27         Thread thread3 = new Thread(new Runnable() {
    28             
    29             @Override
    30             public void run() {
    31                 testSynchronized1.test1();
    32             }
    33         },"test3");
    34         thread1.start();
    35         thread3.start();
    36     }
    37 }

      结果:

      

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

      例子:

     1 public class TestSynchronized {
     2     public void test1(){
     3         synchronized(this) {
     4             System.out.println("1"+this);
     5             int i = 5; 
     6              while( i-- > 0) {
     7                  System.out.println(Thread.currentThread().getName() + " : " + i);  
     8                  try {
     9                     Thread.sleep(500);
    10                 } catch (InterruptedException e) {
    11                     // TODO Auto-generated catch block
    12                     e.printStackTrace();
    13                 }
    14              }
    15         }
    16     }
    17     public synchronized void test2(){
    18         System.out.println(this);
    19         int i = 5; 
    20          while( i-- > 0) {
    21              System.out.println(Thread.currentThread().getName() + " : " + i);  
    22              try {
    23                 Thread.sleep(500);
    24             } catch (InterruptedException e) {
    25                 e.printStackTrace();
    26             }
    27          }
    28     }
    29     public static void main(String[] args) {
    30         final TestSynchronized testSynchronized = new TestSynchronized();
    31         final TestSynchronized testSynchronized1 = new TestSynchronized();
    32         Thread thread1 = new Thread(new Runnable() {
    33             
    34             @Override
    35             public void run() {
    36                 testSynchronized.test1();
    37             }
    38         },"test1");
    39         Thread thread2 = new Thread(new Runnable() {
    40             
    41             @Override
    42             public void run() {
    43                 testSynchronized.test2();
    44             }
    45         },"test2");
    46         thread1.start();
    47         thread2.start();
    48     }
    49 }

      结果:

      

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

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

        例子:

     1 public class TestSynchronized {
     2     public void test1(){
     3         synchronized(this) {
     4             System.out.println("1"+this);
     5             int i = 5; 
     6              while( i-- > 0) {
     7                  System.out.println(Thread.currentThread().getName() + " : " + i);  
     8                  try {
     9                     Thread.sleep(500);
    10                 } catch (InterruptedException e) {
    11                     // TODO Auto-generated catch block
    12                     e.printStackTrace();
    13                 }
    14              }
    15         }
    16     }
    17         //非synchronized
    18     public void test2(){
    19         System.out.println(this);
    20         int i = 5; 
    21          while( i-- > 0) {
    22              System.out.println(Thread.currentThread().getName() + " : " + i);  
    23              try {
    24                 Thread.sleep(500);
    25             } catch (InterruptedException e) {
    26                 e.printStackTrace();
    27             }
    28          }
    29     }
    30     public static void main(String[] args) {
    31         final TestSynchronized testSynchronized = new TestSynchronized();
    32         final TestSynchronized testSynchronized1 = new TestSynchronized();
    33         Thread thread1 = new Thread(new Runnable() {
    34             
    35             @Override
    36             public void run() {
    37                 testSynchronized.test1();
    38             }
    39         },"test1");
    40         Thread thread2 = new Thread(new Runnable() {
    41             
    42             @Override
    43             public void run() {
    44                 testSynchronized.test2();
    45             }
    46         },"test2");
    47         
    48         thread2.start();
    49         thread1.start();
    50     }
    51 }

      结果:

      

    三、加了static后现成的执行

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

      例子:

     1 public class TestSynchronized {
     2     public void test1(){
     3         synchronized(this) {
     4             int i = 5; 
     5              while( i-- > 0) {
     6                  System.out.println(Thread.currentThread().getName() + " : " + i);  
     7                  try {
     8                     Thread.sleep(500);
     9                 } catch (InterruptedException e) {
    10                     // TODO Auto-generated catch block
    11                     e.printStackTrace();
    12                 }
    13              }
    14         }
    15     }
    16     public static synchronized void test2(){
    17         int i = 5; 
    18          while( i-- > 0) {
    19              System.out.println(Thread.currentThread().getName() + " : " + i);  
    20              try {
    21                 Thread.sleep(500);
    22             } catch (InterruptedException e) {
    23                 e.printStackTrace();
    24             }
    25          }
    26     }
    27     public static void main(String[] args) {
    28         final TestSynchronized testSynchronized = new TestSynchronized();
    29         Thread thread1 = new Thread(new Runnable() {
    30             
    31             @Override
    32             public void run() {
                //对象调用的是该对象自己的方法
    33 testSynchronized.test1(); 34 } 35 },"test1"); 36 Thread thread2 = new Thread(new Runnable() { 37 38 @Override 39 public void run() {
               //类调用的是类方法
    40 TestSynchronized.test2(); 41 } 42 },"test2"); 43 thread2.start(); 44 thread1.start(); 45 } 46 }

      结果:

      

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

      例子:

     1 public class TestSynchronized {
     2     public static void test1(){
     3         synchronized(TestSynchronized.class) {
     4             int i = 5; 
     5              while( i-- > 0) {
     6                  System.out.println(Thread.currentThread().getName() + " : " + i);  
     7                  try {
     8                     Thread.sleep(500);
     9                 } catch (InterruptedException e) {
    10                     // TODO Auto-generated catch block
    11                     e.printStackTrace();
    12                 }
    13              }
    14         }
    15     }
    16     public static synchronized void test2(){
    17         int i = 5; 
    18          while( i-- > 0) {
    19              System.out.println(Thread.currentThread().getName() + " : " + i);  
    20              try {
    21                 Thread.sleep(500);
    22             } catch (InterruptedException e) {
    23                 e.printStackTrace();
    24             }
    25          }
    26     }
    27     public static void main(String[] args) {
    28         final TestSynchronized testSynchronized = new TestSynchronized();
    29         Thread thread1 = new Thread(new Runnable() {
    30             
    31             @Override
    32             public void run() {
    33                 TestSynchronized.test1();
    34             }
    35         },"test1");
    36         Thread thread2 = new Thread(new Runnable() {
    37             
    38             @Override
    39             public void run() {
    40                 TestSynchronized.test2();
    41             }
    42         },"test2");
    43         
    44         thread2.start();
    45         thread1.start();
    46     }
    47 }

      结果:

      

    补充:

      面试的一道题:

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

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

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

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

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

      

      

        

      

        

  • 相关阅读:
    placement new小结
    template template parameter 模板模板参数
    windows下创建和删除软链接
    gcc下载地址
    map的erase函数小结
    typedef函数指针
    宏定义条件编译中使用多条件
    关于c++模板特例化测试
    tolua使用
    c++多态
  • 原文地址:https://www.cnblogs.com/rgever/p/9756939.html
Copyright © 2011-2022 走看看