`

java中中synchronized的用法详解

    博客分类:
  • java
 
阅读更多
1.对象锁:
  1.1对象锁是run方法所在类的实例
  synchronized 修饰非静态方法,或者  synchronized(this)时
   public synchronized void method() { // todo }与
   public void method(){synchronized(this) {// todo} }等价
  1.1.1 结论:
  当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
1.1.1示例说明:
  public class ThreadTest implements  Runnable{

public  void run() {
method1();
}

private synchronized void method1(){
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
ThreadTest obj1= new  ThreadTest();
Thread  t1= new Thread(obj1,"线程1");
Thread t2= new  Thread(obj1,"线程2");
t1.start();
t2.start();
}
}
1.1.1执行结果:
线程1:  0
线程1:  1
线程1:  2
线程1:  3
线程1:  4
线程2:  0
线程2:  1
线程2:  2
线程2:  3
线程2:  4
  1.1.2结论:当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块.
  1.1.2示例说明:
  public class ThreadTest implements  Runnable{

public  void run() {
if("线程1".equals(Thread.currentThread().getName())){
method1();
}else{
method2();
}

}

private synchronized void method1(){
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

private  void method2(){
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
ThreadTest obj1= new  ThreadTest();
Thread  t1= new Thread(obj1,"线程1");
Thread t2= new  Thread(obj1,"线程2");
t1.start();
t2.start();
}
}
1.1.2执行结果:
线程1:  0
线程2:  0
线程1:  1
线程2:  1
线程2:  2
线程1:  2
线程1:  3
线程2:  3
线程1:  4
线程2:  4
1.1.3结论:
  当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞
1.1.3示例代码:
  更改1.1.2的method2方法,
  在method2上添加synchronized
  private  synchronized void method2(){
  //....
         }
  或者
   private   void method2(){synchronized(this){
    //..
  }}
1.1.3 执行结果
线程1:  0
线程1:  1
线程1:  2
线程1:  3
线程1:  4
线程2:  0
线程2:  1
线程2:  2
线程2:  3
线程2:  4
1.1.4结论:
  多个线程访问不同的对象时,不会存在互斥的情况
  1.1.4 示例代码:
      将1.1.4 示例代码的main改为如下:(每个线程访问不同的对象)
      public static void main(String[] args) {
ThreadTest obj1= new  ThreadTest();
ThreadTest obj2= new  ThreadTest();
Thread  t1= new Thread(obj1,"线程1");
Thread t2= new  Thread(obj2,"线程2");
t1.start();
t2.start();
}
  1.1.4 执行结果
线程1:  0
线程2:  0
线程2:  1
线程1:  1
线程1:  2
线程2:  2
线程1:  3
线程2:  3
线程1:  4
线程2:  4

1.2 对象锁不是run方法所在类的实例
 
  1.2.1 指定要给某个对象加锁

  1.2.1 示例代码
  class Account {
   String name;
   float amount;

   public Account(String name, float amount) {
      this.name = name;
      this.amount = amount;
   }
   //存钱
   public  void deposit(float amt) {
      amount += amt;
      try {
         Thread.sleep(100);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
   }
   //取钱
   public  void withdraw(float amt) {
      amount -= amt;
      try {
         Thread.sleep(100);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
   }

   public float getBalance() {
      return amount;
   }
}
      class AccountOperator implements Runnable{
   private Account account;
   public AccountOperator(Account account) {
      this.account = account;
   }

   public void run() {
      synchronized (account) {
         account.deposit(500);
         account.withdraw(500);
         System.out.println(Thread.currentThread().getName() + ":" + account.getBalance());
      }
   }
  
   public static void main(String[] args) {
   Account account = new Account("zhang san", 10000.0f);
   AccountOperator accountOperator = new AccountOperator(account);

   final int THREAD_NUM = 5;
   Thread threads[] = new Thread[THREAD_NUM];
   for (int i = 0; i < THREAD_NUM; i ++) {
      threads[i] = new Thread(accountOperator, "Thread" + i);
      threads[i].start();
   }
}
}

1.2.1 执行结果:
Thread0:10000.0
Thread4:10000.0
Thread3:10000.0
Thread2:10000.0
Thread1:10000.0

说明:account作为锁对象,起到了同步的效果

1.2.2 只是想让一段代码同步时,可以创建一个特殊的对象来充当锁:
  创建 byte[] lock= new byte[0];比创建Object开销小,所以推荐byte[0]。
示例代码:
public class ThreadTest implements  Runnable{
byte[] lock= new byte[0];
public  void run() {
method2();
}



private    void method2(){
synchronized (lock) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
ThreadTest obj1= new  ThreadTest();
Thread  t1= new Thread(obj1,"线程1");
Thread t2= new  Thread(obj1,"线程2");
t1.start();
t2.start();
}
}

执行结果:
线程1:  0
线程1:  1
线程1:  2
线程1:  3
线程1:  4
线程2:  0
线程2:  1
线程2:  2
线程2:  3
线程2:  4

说明:这种方式结果看似与private synchronized    void method2(){//..}一致,但是synchronized (lock) 的锁是lock,而private synchronized    void method2()锁是this。

1.2.3  静态的成员作为锁:
将示例1.2.2中byte[] lock= new byte[0]; 改为static byte[] lock= new byte[0];
这样,lock就只有一份,任何时候,最多一个线程进入到lock锁定的执行体
 
1.2.4 常量作为锁
  public class ThreadTest2 implements  Runnable{
public  void run() {
method1();
}

private    void method1(){
synchronized ("123") {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}
}

  public class ThreadTest implements  Runnable{

public  void run() {
method1();

}

private    void method1(){
synchronized ("123") {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}



public static void main(String[] args) {
ThreadTest obj1= new  ThreadTest();
ThreadTest2 obj2= new  ThreadTest2();
Thread  t1= new Thread(obj1,"线程1");
Thread t2= new  Thread(obj2,"线程2");
t1.start();
t2.start();
}
}
说明:常量作为锁,所有的用到这个常量的同步,都只能有一个线程能执行,不推荐

2.类锁:
synchronized 修饰静态方法 或者    synchronized(类名.class) {  // todo}
    public   static synchronized void methodB() {
    }
    与
    public  void methodB() {  
       synchronized(所在类.class){
       }
    }
   在多线程层面上来看,是等价的


示例2.1:
public class ThreadTest implements  Runnable{

public  void run() {
if("线程1".equals(Thread.currentThread().getName())){
method1();
}else{
method2();
}

}

private synchronized static  void method1(){
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

private synchronized static  void method2(){
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
ThreadTest obj1= new  ThreadTest();
ThreadTest obj2= new  ThreadTest();
Thread  t1= new Thread(obj1,"线程1");
Thread t2= new  Thread(obj2,"线程2");
t1.start();
t2.start();
}
}

执行结果:
线程1:  0
线程1:  1
线程1:  2
线程1:  3
线程1:  4
线程2:  0
线程2:  1
线程2:  2
线程2:  3
线程2:  4

解释说明:
这里的锁是ThreadTest 类,所有对象共用这一把锁。

示例2.2
public class ThreadTest implements  Runnable{

public  void run() {
if("线程1".equals(Thread.currentThread().getName())){
method1();
}else{
method2();
}

}

private synchronized static  void method1(){
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

private  synchronized  void method2(){
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+":  "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
ThreadTest obj1= new  ThreadTest();
Thread  t1= new Thread(obj1,"线程1");
Thread t2= new  Thread(obj1,"线程2");
t1.start();
t2.start();
}
}

执行结果:
线程1:  0
线程2:  0
线程2:  1
线程1:  1
线程2:  2
线程1:  2
线程1:  3
线程2:  3
线程1:  4
线程2:  4


解释说明:
因为method1的锁是ThreadTest 类,而method2的锁是当前对象(也就是这里的obj1),锁不同,不会互斥。

线程通俗描述:
一个object就像一个大房子,大门永远打开。房子里有 很多房间(也就是方法)。
这些房间有上锁的(synchronized方法), 和不上锁之分(普通方法)。房子外放着一把钥匙(key),这把钥匙可以打开所有上锁的房间。所有想调用该对象方法的线程比喻成想进入这房子某个房间的人。第一个人进入房间后,房子外来了2个人,这两个人要等,第一个人从房间内出来,即使他还想去其他房间,也要把钥匙还回来,重新竞争。
分享到:
评论

相关推荐

    java中synchronized用法

    "Java 中 synchronized 用法详解" Synchronized 是 Java 语言中用于解决多线程共享数据同步问题的关键字。它可以作为函数的修饰符,也可以作为函数内的语句,用于实现同步方法和同步语句块。在 Java 中,...

    java里面synchronized用法.doc

    Java 中的 synchronized 用法详解 Java 中的 synchronized 关键字是用于解决多线程并发问题的重要工具之一。它可以被用于方法、代码块和变量上,以实现对共享资源的互斥访问控制。本文将对 Java 中的 synchronized ...

    java同步synchronized关键字用法示例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源时的同步机制。在Java中,当多个线程试图同时访问和修改同一块代码或数据时,可能会导致数据不一致的问题。为了解决这个问题,...

    java_synchronized详解

    ### Java synchronized 关键字详解 #### 一、synchronized关键字简介 `synchronized`是Java语言提供的关键字之一,用于实现线程间的同步控制。通过在方法或代码块上使用`synchronized`,可以确保同一时间只有一个...

    Java 中 synchronized的用法详解(四种用法)

    理解 `synchronized` 的工作原理和用法对于编写线程安全的 Java 代码至关重要。然而,过度使用 `synchronized` 可能会导致性能下降,因为它会阻塞线程。因此,开发者需要谨慎地权衡同步的粒度,尽可能减少锁的范围,...

    Java-synchronized详解.docx

    Java synchronized 详解 Java 中的同步机制是多线程编程中最重要的概念之一。它允许开发者控制多个线程对共享资源的访问,以避免数据不一致和race condition。这篇文章将详细介绍 Java 中的 synchronized 机制,...

    java-synchronized详解.doc

    对于一些复杂场景,如读写操作,`synchronized`可能不是最佳选择,可以考虑使用`java.util.concurrent`包中的高级并发工具,如`ReentrantLock`、`Semaphore`等。 总结来说,`synchronized`是Java中实现线程同步的...

    java关键字Synchronized详解

    总的来说,synchronized是Java中保证线程安全的重要工具,它通过锁机制实现了对共享资源的访问控制,但过度使用或不当使用可能会导致性能下降。理解其工作原理和优化策略,有助于编写高效、线程安全的Java代码。

    synchronized关键字的用法详解

    `synchronized`关键字有两种主要的使用方式:一种是在方法声明中使用,另一种则是在代码块中使用。 ##### 1. synchronized方法 在方法声明中添加`synchronized`关键字,可以将整个方法体变成同步代码块。例如: `...

    Java synchronized使用案例

    在`Synchronized`压缩包中,可能包含了通过实验来演示`synchronized`关键字使用的一些Java代码。例如,创建一个共享资源类,然后通过多个线程去操作这个资源,使用`synchronized`关键字来保证线程安全。实验可能涉及...

    Java多线程synchronized关键字详解(六)共5

    本篇将详细解析`synchronized`的关键特性和使用方法,帮助开发者深入理解如何在并发编程中有效地利用这一特性。 1. **synchronized的两种使用方式** - **方法同步**:通过在方法声明前加上`synchronized`关键字,...

    java锁机制Synchronizedjava锁机制Synchronized

    "Java 锁机制 Synchronized" Java 锁机制 Synchronized 是 Java 语言中的一种同步机制,用于解决多线程并发访问共享资源时可能出现的一些问题。 Java 锁机制 Synchronized 的概念 在 Java 中,每个对象都可以被...

    java中synchronized的使用

    java中synchronized的使用,java中的锁锁的到底是什么?是括号里的代码块吗?肯定不是的;

    Java 同步锁(synchronized)详解及实例

    Java中的同步锁,即`synchronized`关键字,是Java多线程编程中用于解决并发问题的重要机制。它确保了对共享资源的互斥访问,防止数据的不一致性。当我们有多线程环境并涉及到共享数据时,可能会出现竞态条件,就像...

    java-synchronized 嵌套使用代码详解

    java-synchronized 嵌套使用代码详解 java-synchronized 嵌套使用是 Java 编程语言中的一种同步机制,用于解决多线程并发执行时的线程安全问题。通过使用 synchronized 关键字,可以将某个对象或代码块锁定,使得...

    Java中synchronized正确使用方法解析

    Java 中 synchronized 正确使用方法解析 Java 中 synchronized 关键字是解决线程安全问题的重要手段,它可以确保在多线程环境下,共享资源的访问安全性。本文将详细介绍 Java 中 synchronized 的正确使用方法,通过...

    java synchronized详解

    java synchronized详解

    JAVA synchronized详解

    ### JAVA synchronized详解 在Java编程语言中,`synchronized`是一个非常重要的关键字,它主要用于实现同步控制机制。通过使用`synchronized`,可以确保同一时刻只有一个线程能够访问被标记为同步的方法或代码块,...

Global site tag (gtag.js) - Google Analytics