zoukankan      html  css  js  c++  java
  • Java synchronized同步 各方式略解

      近段为了实现一个功能,在树结构中,修改某个节点名称时,需要同时修改这个节点所有子节点的节点全路径属性字段(类似"父父节点名称/父节点名称/子节点名称/子子节点名称"的构造)。因为在构造Update语句时,需要递归去查询子节点以及构造全路径的值,需要花费了一定的时间,等批量执行update语句时,可能子节点的某个子节点的名称又改变了,会引起冲突,故用到了synchronized,顺便了解了下实现方式,原理没深入了解,在此记录以便日后查看。

    -----------------------------------------------------我是正文分割线--------------------我是正文分割线---------------------------

    本文主要列举不同的同步方式,以及我理解的使用范围。

    众所周知,同步分为两种用法:同步方法、与同步块。

    一、同步块

    1.1 类同步(非静态方法)

    · 实现方式:

     1 public class JustPlayServiceImplSyn2 {
     2     
     3     public JustPlayServiceImplSyn2(){
     4         
     5     }
     6     private static int flag = 1;
     7     public void operate() { 
     8         synchronized(JustPlayServiceImplSyn2.class){
     9             flag++; 
    10             try { 
    11                 // 增加随机性,让不同线程能在此交替执行 
    12                 Thread.sleep(new Random().nextInt(5)); 
    13             } catch (InterruptedException e) { 
    14                 e.printStackTrace(); 
    15             } 
    16             flag--; 
    17             System.out.println("Thread: " + Thread.currentThread().getName() 
    18                     + " /Current flag: " + flag);
    19         }
    20     }
    21 }
    View Code

    · 测试代码:

     1 public class JustPlay {
     2     /**
     3      * @param args
     4      */
     5     public static void main(String[] args) {
     6                new Thread("Thread-01") { 
     7                    public void run() { 
     8                        new JustPlayServiceImplSyn2().operate();
     9                     } 
    10                }.start(); // 启动第一个线程
    11                
    12          new Thread("Thread-02") { 
    13                    public void run() { 
    14                        new JustPlayServiceImplSyn2().operate();
    15                    } 
    16                }.start(); // 启动第一个线程
    17     }
    18 }
    View Code

    · 使用范围:多对象多线程的同步。
      使用范围最广,代码也简单,在需要同步的代码块上加上synchronized关键字,并在括号类用[类名.class]就行。

    1.2 this同步(非静态方法)

    · 实现方式:

     1 public class JustPlayServiceImplSyn2 {
     2     
     3     public JustPlayServiceImplSyn2(){
     4         
     5     }
     6     private static int flag = 1;
     7     public  void operate_this() { 
     8         synchronized(this){
     9             flag++; 
    10             try { 
    11                 // 增加随机性,让不同线程能在此交替执行 
    12                 Thread.sleep(new Random().nextInt(5)); 
    13             } catch (InterruptedException e) { 
    14                 e.printStackTrace(); 
    15             } 
    16             flag--; 
    17             System.out.println("Thread: " + Thread.currentThread().getName() 
    18                     + " /Current flag: " + flag);
    19         }
    20     }
    21 }
    View Code

    · 测试代码:

     1 public class JustPlay {
     2 
     3     /**
     4      * @param args
     5      */
     6     public static void main(String[] args) {
     7         final JustPlayServiceImplSyn2  justplayserviceimplsyn2= new JustPlayServiceImplSyn2();
     8            for(int i=0;i<100;i++){
     9                new Thread("Thread-001"){
    10                    public void run() {
    11                        justplayserviceimplsyn2.operate_this();
    12                    }
    13                }.start();
    14                new Thread("Thread-002"){
    15                    public void run() {
    16                        justplayserviceimplsyn2.operate_this();
    17                    }
    18                }.start();
    19     }
    20 }
    View Code

    · 使用范围:单对象多线程的同步。

      在synchronized关键字后的括号内用this关键字。使用[this]同步时需要是同一对象的才能同步,多对象时是同步失败的。因为同步是对this对象锁,不同对象时锁互不影响

    1.3 静态对象同步(非静态方法)

    · 实现方式:

     1 public class JustPlayServiceImpl {
     2     private static JustPlayServiceImpl myobj = null;
     3     
     4     private JustPlayServiceImpl(){
     5         
     6     }
     7     public static JustPlayServiceImpl createJustPlayServiceImpl(){
     8         if(myobj==null){
     9             myobj = new JustPlayServiceImpl();
    10         }
    11         return myobj;
    12     }
    13     private static int flag = 1;
    14     public void operate() { 
    15         synchronized(myobj){
    16             flag++; 
    17             try { 
    18                 // 增加随机性,让不同线程能在此交替执行 
    19                 Thread.sleep(new Random().nextInt(5)); 
    20             } catch (InterruptedException e) { 
    21                 e.printStackTrace(); 
    22             } 
    23             flag--; 
    24             System.out.println("Thread: " + Thread.currentThread().getName() 
    25                     + " /Current flag: " + flag);
    26         }
    27     }
    28 }
    View Code

    · 测试代码:

     1 public class JustPlay {
     2 
     3     /**
     4      * @param args
     5      */
     6     public static void main(String[] args) {
     7 
     8            for(int i=0;i<100;i++){
     9               new Thread("Thread-01") { 
    10                    public void run() { 
    11                        JustPlayServiceImpl.createJustPlayServiceImpl().operate())                   } 
    12                }.start(); // 启动第一个线程
    13           new Thread("Thread-02") { 
    14                    public void run() { 
    15                        JustPlayServiceImpl.createJustPlayServiceImpl().operate()                   } 
    16                }.start(); // 启动第二个线程
    17            }
    View Code

    · 使用范围:单体类单对象多线程的同步。

      因为同步是对对象的同步锁,只要保证同步块对象唯一,就能实现同步。偷点懒,我直接将类变成了单体类,然后将唯一对象给锁了。(ps:怎么感觉有点鬼畜。。。哈哈哈)

    二、同步方法

    2.1 静态方法同步

    · 实现方式:

     1 public class JustPlayServiceImplSyn2 {
     2     
     3     public JustPlayServiceImplSyn2(){
     4         
     5     }
     6     private static int flag = 1;
     7     public synchronized static void operate_static(){
     8         flag++; 
     9         try { 
    10             // 增加随机性,让不同线程能在此交替执行 
    11             Thread.sleep(new Random().nextInt(5)); 
    12         } catch (InterruptedException e) { 
    13             e.printStackTrace(); 
    14         } 
    15         flag--; 
    16         System.out.println("Thread: " + Thread.currentThread().getName() 
    17                 + " /Current flag: " + flag);
    18     }
    19 }
    View Code

    · 测试代码:

     1 public class JustPlay {
     2 
     3     /**
     4      * @param args
     5      */
     6     public static void main(String[] args) {
     7            for(int i=0;i<100;i++){
     8               new Thread("Thread-01") { 
     9                    public void run() { 
    10                        JustPlayServiceImplSyn2.operate_static();
    11                    } 
    12                }.start(); // 启动第一个线程
    13                
    14          new Thread("Thread-02") { 
    15                    public void run() { 
    16                        JustPlayServiceImplSyn2.operate_static();
    17                    } 
    18                }.start(); // 启动第一个线程
    19         }
    20     }
    21 }
    View Code

    · 使用范围:静态方法单对象多线程的同步。

      再次说[因为同步是对对象的同步锁],而且调用静态方法绑定的是类而不是对象,所以,同步了静态方法,就是将相当于将类给锁了,然后就同步了。原理与[1.1 类同步(非静态方法)]一致。

    2.2 非静态方法同步

      2.2.1 单体类非静态方法同步

      ·  实现方式:  

     1 public class JustPlayServiceImpl {
     2     private static JustPlayServiceImpl myobj = null;
     3     
     4     private JustPlayServiceImpl(){
     5         
     6     }
     7     public static JustPlayServiceImpl createJustPlayServiceImpl(){
     8         if(myobj==null){
     9             myobj = new JustPlayServiceImpl();
    10         }
    11         return myobj;
    12     }
    13     private static int flag = 1;
    14     
    15     //单体类 此种同步方式有效
    16     public synchronized void operate2() { 
    17             flag++; 
    18             try { 
    19                 // 增加随机性,让不同线程能在此交替执行 
    20                 Thread.sleep(new Random().nextInt(5)); 
    21             } catch (InterruptedException e) { 
    22                 e.printStackTrace(); 
    23             } 
    24             flag--; 
    25             System.out.println("Thread: " + Thread.currentThread().getName() 
    26                     + " /Current flag: " + flag);
    27     }
    28 }
    View Code

      · 测试代码:

     1     public static void main(String[] args) {
     2 
     3            for(int i=0;i<100;i++){
     4               new Thread("Thread-01") { 
     5                    public void run() { 
     6                        JustPlayServiceImpl.createJustPlayServiceImpl().operate2();
     7                    } 
     8                }.start(); // 启动第一个线程
     9                
    10            new Thread("Thread-02") { 
    11                    public void run() { 
    12                       JustPlayServiceImpl.createJustPlayServiceImpl().operate2();
    13                    } 
    14                }.start(); // 启动第一个线程
    15            }
    16         }
    17 }
    View Code

      · 使用范围:单体类单对象多线程的同步。

        原理同[1.3 静态对象同步(非静态方法)]

      2.2.2 非单体类非静态方法同步

      · 实现方式:

     1 public class JustPlayServiceImplSyn2 {
     2     
     3     public JustPlayServiceImplSyn2(){
     4         
     5     }
     6     private static int flag = 1;
     7     //适用于单对象多线程
     8     public synchronized void operate2() { 
     9             flag++; 
    10             try { 
    11                 // 增加随机性,让不同线程能在此交替执行 
    12                 Thread.sleep(new Random().nextInt(5)); 
    13             } catch (InterruptedException e) { 
    14                 e.printStackTrace(); 
    15             } 
    16             flag--; 
    17             System.out.println("Thread: " + Thread.currentThread().getName() 
    18                     + " /Current flag: " + flag);
    19     }
    20 }
    View Code

      · 测试代码:

     1 public class JustPlay {
     2 
     3     /**
     4      * @param args
     5      */
     6     public static void main(String[] args) {
     7         final JustPlayServiceImplSyn2  justplayserviceimplsyn2= new JustPlayServiceImplSyn2();
     8            for(int i=0;i<100;i++){
     9                new Thread("Thread-001"){
    10                    public void run() {
    11                        justplayserviceimplsyn2.operate2();
    12                    }
    13                }.start();
    14                new Thread("Thread-002"){
    15                    public void run() {
    16                        justplayserviceimplsyn2.operate2();
    17                    }
    18                }.start();
    19         }
    20 }
    View Code

      · 使用范围:单对象多线程的同步。

        原理同[1.2 this同步(非静态方法)]

    总结:对于网页用ajax方式多次调用的class,因为是多线程且不可控为单一对象,若想同步:解决方案是:1.1、1.3、2.1、2.2.1;对于1.2和2.2.2,调用的对象必须是保持同一个才会同步。

    PS:觉得应该还有其他方式,隐隐的这么觉得。。。。。哈哈哈哈哈哈

    ------------------------------------结束的分割线--------------结束的分割线------------------有机会再去了解同步的底层原理去了----那时候再写原理------またね!---

  • 相关阅读:
    Visual Studio DSL 入门 11为状态机设计器添加规则
    不平静的2009,期待更不平静的2010
    ASP.NET MVC 2 正式发布
    [翻译] DSL和模型驱动开发的最佳实践(2/4)
    Visual Studio DSL 入门 9创建状态机的图形符号
    Visual Studio DSL 入门 6DSL的图形表示1
    智诚B2C1.31正式发
    一个程序员的创业尝试
    Visual Studio DSL 入门 13结合T4生成代码
    Visual Studio DSL 入门 10完善状态机案例
  • 原文地址:https://www.cnblogs.com/jkgyu/p/4919223.html
Copyright © 2011-2022 走看看