`

[zz] Synchronized和Static Synchronized区别

 
阅读更多

 通过分析这两个用法的分析,我们可以理解java中锁的概念。一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全局锁(该锁针对的是类,无论实例多少个对象,那么线程都共享该锁)。实例锁对应的就是synchronized关键字,而类锁(全局锁)对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。下面的文章做了很好的总结:

 

1.synchronized与static synchronized 的区别
       synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是“类的当前实例”, 类的两个不同实例就没有这种约束了。那么static synchronized恰好就是要控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例同时访问对应的代码快。实际上,在类中某方法或某代码块中有 synchronized,那么在生成一个该类实例后,改类也就有一个监视快,放置线程并发访问改实例synchronized保护快,而static synchronized则是所有该类的实例公用一个监视快了,也也就是两个的区别了,也就是synchronized相当于 this.synchronized,而static synchronized相当于Something.synchronized.


         一个日本作者-结成浩的《java多线程设计模式》有这样的一个列子:

  1. pulbic class Something(){  
  2.     public synchronized void isSyncA(){}  
  3.     public synchronized void isSyncB(){}  
  4.     public static synchronized void cSyncA(){}  
  5.     public static synchronized void cSyncB(){}  
  6. }  


       那么,加入有Something类的两个实例a与b,那么下列组方法何以被1个以上线程同时访问呢

  1. a. x.isSyncA()与x.isSyncB()   
  2. b. x.isSyncA()与y.isSyncA()  
  3. c. x.cSyncA()与y.cSyncB()  
  4. d. x.isSyncA()与Something.cSyncA()  


      这里,很清楚的可以判断:
a,都是对同一个实例的synchronized域访问,因此不能被同时访问
b,是针对不同实例的,因此可以同时被访问
c,因为是static synchronized,所以不同实例之间仍然会被限制,相当于Something.isSyncA()与 Something.isSyncB()了,因此不能被同时访问。
那么,第d呢?,书上的 答案是可以被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同的原因。
个人分析也就是synchronized 与static synchronized 相当于两帮派,各自管各自,相互之间就无约束了,可以被同时访问。目前还不是分清楚java内部设计synchronzied是怎么样实现的。


结论:A: synchronized static是某个类的范围,synchronized static cSync{}防止多个线程同时访问这个 类中的synchronized static 方法。它可以对类的所有对象实例起作用。

B: synchronized 是某实例的范围,synchronized isSync(){}防止多个线程同时访问这个实例中的synchronized 方法。



2.synchronized方法与synchronized代码快的区别
        synchronized methods(){} 与synchronized(this){}之间没有什么区别,只是
synchronized methods(){} 便于阅读理解,而synchronized(this){}可以更精确的控制冲突限制访问区域,有时候表现更高效率。


3.synchronized关键字是不能继承的
        这个在
http://www.learndiary.com/archives/diaries/2910.htm一文中看到的,我想这一点也是很值得注意的,继承时子类的覆盖方法必须显示定义成synchronized。(但是如果使用继承开发环境的话,会默认加上synchronized关键字)

两种方式效率比较:

1、同步块,代码如下:

  1. <span style="font-size:18px;">package com.bjtest.belen;  
  2. import java.util.concurrent.CountDownLatch;  
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5.   
  6. public class TestSynchronized {  
  7.   
  8.         /** 
  9.          * @param args 
  10.          */  
  11.         public static void main(String[] args) {  
  12.               
  13.             ExecutorService service = Executors.newCachedThreadPool();  
  14.             final CountDownLatch cdOrder = new CountDownLatch(1);  
  15.             final CountDownLatch cdAnswer = new CountDownLatch(3);  
  16.               
  17.             final SynchonizedClass sc = new SynchonizedClass();  
  18.             for(int i=0; i<3; i++){  
  19.                 Runnable runnable = new Runnable(){  
  20.   
  21.                     public void run() {  
  22.                         try{  
  23.                             cdOrder.await();  
  24.                             sc.start();  
  25.                             cdAnswer.countDown();  
  26.                         }catch(Exception e){  
  27.                             e.printStackTrace();  
  28.                         }  
  29.                     }  
  30.                       
  31.                 };  
  32.                 service.execute(runnable);  
  33.             }  
  34.             try{  
  35.                 Thread.sleep((long) (Math.random()*10000));  
  36.                 System.out.println("线程" + Thread.currentThread().getName() +   
  37.                         "发布执行命令");  
  38.                 cdOrder.countDown();  
  39.                 long beginTime = System.currentTimeMillis();  
  40.                 System.out.println("线程" + Thread.currentThread().getName() +   
  41.                 "已经发送命令,正在等待结果");  
  42.                 cdAnswer.await();  
  43.                 System.out.println("线程" + Thread.currentThread().getName() +   
  44.                 "已收到所有响应结果,所用时间为:" + (System.currentTimeMillis()-beginTime));  
  45.             }catch(Exception e){  
  46.                 e.printStackTrace();  
  47.             }  
  48.             service.shutdown();  
  49.     }  
  50. }  
  51.   
  52. class SynchonizedClass{  
  53.       
  54.     public void start() throws InterruptedException{  
  55.           
  56.         Thread.sleep(100);//执行其它逻辑消耗时间   
  57.         synchronized(this){  
  58.          System.out.println("我运行使用了 10 ms");  
  59.         }  
  60.     }  
  61. }  
  62. </span>  


运行结果如下:

线程main发布执行命令
线程main已经发送命令,正在等待结果
我运行使用了 10 ms
我运行使用了 10 ms
我运行使用了 10 ms
线程main已收到所有响应结果,所用时间为:110

 

同步方法,代码如下:

  1. <span style="font-size:18px;">package com.bjtest.belen;  
  2. import java.util.concurrent.CountDownLatch;  
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5.   
  6. public class TestSynchronized {  
  7.   
  8.         /** 
  9.          * @param args 
  10.          */  
  11.         public static void main(String[] args) {  
  12.               
  13.             ExecutorService service = Executors.newCachedThreadPool();  
  14.             final CountDownLatch cdOrder = new CountDownLatch(1);  
  15.             final CountDownLatch cdAnswer = new CountDownLatch(3);  
  16.               
  17.             final SynchonizedClass sc = new SynchonizedClass();  
  18.             for(int i=0; i<3; i++){  
  19.                 Runnable runnable = new Runnable(){  
  20.   
  21.                     public void run() {  
  22.                         try{  
  23.                             cdOrder.await();  
  24.                             sc.start();  
  25.                             cdAnswer.countDown();  
  26.                         }catch(Exception e){  
  27.                             e.printStackTrace();  
  28.                         }  
  29.                     }  
  30.                       
  31.                 };  
  32.                 service.execute(runnable);  
  33.             }  
  34.             try{  
  35.                 Thread.sleep((long) (Math.random()*10000));  
  36.                 System.out.println("线程" + Thread.currentThread().getName() +   
  37.                         "发布执行命令");  
  38.                 cdOrder.countDown();  
  39.                 long beginTime = System.currentTimeMillis();  
  40.                 System.out.println("线程" + Thread.currentThread().getName() +   
  41.                 "已经发送命令,正在等待结果");  
  42.                 cdAnswer.await();  
  43.                 System.out.println("线程" + Thread.currentThread().getName() +   
  44.                 "已收到所有响应结果,所用时间为:" + (System.currentTimeMillis()-beginTime));  
  45.             }catch(Exception e){  
  46.                 e.printStackTrace();  
  47.             }  
  48.             service.shutdown();  
  49.     }  
  50. }  
  51.   
  52. class SynchonizedClass{  
  53.       
  54.     public synchronized void start() throws InterruptedException{  
  55.           
  56.         Thread.sleep(100);//执行其它逻辑消耗时间   
  57. //      synchronized(this){   
  58.          System.out.println("我运行使用了 10 ms");  
  59. //      }   
  60.     }  
  61. }  
  62. </span>  

运行结果如下:

线程main发布执行命令
线程main已经发送命令,正在等待结果
我运行使用了 10 ms
我运行使用了 10 ms
我运行使用了 10 ms
线程main已收到所有响应结果,所用时间为:332

两者相差:222ms。

分享到:
评论

相关推荐

    透彻理解Java中Synchronized(对象锁)和Static Synchronized(类锁)的区别

    Java 中 Synchronized(对象锁)和 Static Synchronized(类锁)的区别 Synchronized 和 Static Synchronized 是 Java 中两种同步机制,它们都用于解决多线程并发访问的安全问题。然而,它们之间存在着本质的区别。...

    synchronized与static synchronized的区别

    大家在学习java多线程的时候肯定会遇到这个...static synchronized这个是“全局锁”或者是“类锁”,该锁针对的是类,不管实例了多少个对象,线程都共享该锁。 下面我们来看代码: import java.util.concurrent.TimeUni

    volatile和synchronized的区别

    ### volatile与synchronized的区别 #### 一、锁的特性:互斥与可见性 在并发编程中,锁作为实现线程安全的一种手段,其核心作用在于提供两种特性:互斥和可见性。 - **互斥**:互斥是指在任何时刻,只允许一个...

    ReentrantLock与synchronized区别

    java语言 并发编程 ReentrantLock与synchronized区别 详解

    java的lock和synchronized的区别.docx

    Java 中的 Lock 和 Synchronized 的区别 Java 语言中有很多相似关键字或相似意义的字,但 lock 和 synchronized 是两个最容易混淆的关键字。它们都是锁的意思,都是为了线程安全性、应用合理性和运行效率的。下面...

    第15讲 synchronized和ReentrantLock有什么区别呢?1

    在Java编程中,synchronized和ReentrantLock都是用于实现线程同步的重要工具,它们在并发控制方面扮演着关键角色。然而,两者之间存在一些显著的区别,这些差异体现在功能、灵活性、性能以及使用场景上。 首先,...

    java中synchronized用法

    在 Java 中,synchronized 关键字可以作用于 instance 变量、object reference(对象引用)、static 函数和 class literals(类名称字面常量)身上。 Synchronized 关键字的作用是取得对象的锁,而不是把一段代码或...

    java里面synchronized用法.doc

    public static synchronized void myStaticMethod() { // ... } } ``` 在上面的例子中,synchronized 关键字被用于静态方法 myStaticMethod 上,以防止多个线程同时访问同一个类中的静态方法。 二、synchronized...

    synchronized的几种示例

    public static synchronized void staticMethod() { // 方法体 } } ``` 在这里,`staticMethod`锁定了`MyClass`类的Class对象,因此任何线程调用`staticMethod`都会互斥。 总结来说,`synchronized`关键字在...

    synchronized用法大全实例

    public static synchronized void method() { // ... } } ``` - **对象锁**:如果`synchronized`修饰非静态方法或者同步语句块中的对象引用是实例引用,那么锁定的是该实例对象。例如: ```java public ...

    synchronized并发讲解源码.zip

    public static synchronized void method() { // ... } } ``` 在这种情况下,所有线程对`method()`的访问都会互斥,无论它们是否共享同一个对象实例。 除了锁住对象或类,`synchronized`还可以与`wait()`、`...

    Synchronized与ThreadLocal

    #### 三、Synchronized与ThreadLocal的区别 - **同步机制:** - Synchronized 是通过加锁来实现同步,确保同一时刻只有一个线程能访问被同步的代码块或方法。 - ThreadLocal 并不提供同步机制,而是为每个线程...

    java锁机制Synchronizedjava锁机制Synchronized

    这些房间可以被分为两种:上锁房间(synchronized 方法)和不上锁房间(普通方法)。每个对象都有一个钥匙(key),该钥匙可以打开所有上锁的房间。 Synchronized 方法 当一个线程想要进入一个上锁房间时,它需要...

    JAVA synchronized详解

    public static synchronized void staticMethod() { // 方法体 } } ``` ##### 2. 同步代码块 除了同步方法之外,还可以通过`synchronized`关键字来同步一段代码块,这种情况下需要指定同步监视器(锁对象),...

    java_synchronized详解

    通过在方法或代码块上使用`synchronized`,可以确保同一时间只有一个线程能访问这些代码区域,从而有效避免了多线程环境下的数据竞争和不一致性问题。 #### 二、synchronized的作用机制 `synchronized`主要通过对象...

    Android synchronized 测试案例

    `synchronized`关键字可以修饰方法或用作代码块,其主要作用是控制对共享资源的并发访问,防止数据不一致和竞态条件。当一个线程进入`synchronized`代码块或方法时,其他试图进入同一块的线程将被阻塞,直到持有锁的...

    volatile与synchronized的区别

    volatile与synchronized的区别,锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)

    Synchronized关键字的用法

    通过`synchronized`关键字,开发者可以控制代码块或方法的并发访问,从而确保数据的一致性和程序的正确性。 #### 使用场景 1. **同步代码块**:可以通过`synchronized`关键字来声明同步代码块,即通过指定对象锁来...

    java同步synchronized关键字用法示例

    volatile与synchronized的区别** `synchronized`提供了数据一致性,但会阻止线程并发执行,造成阻塞。而`volatile`关键字则可以保证变量的可见性,但不会提供互斥访问。因此,`volatile`通常用于读多写少的情况,...

    Java synchronized使用案例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,以保证数据的一致性和完整性。这个关键词提供了互斥锁机制,防止多个线程同时执行同一段代码,确保了线程安全。 一、`...

Global site tag (gtag.js) - Google Analytics