Junior Farmer

真正了不起的程序员对自己程序的每一个字节都了如指掌
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Java之线程同步的三种方法

Posted on 2013-10-15 10:12  农少  阅读(224)  评论(0编辑  收藏  举报

第一种:同步代码块

同步代码块的核心是设置同步监视器,原则上在Java中可以设置任何对象为同步监视器,但通常设置可能并发访问的共享资源对象为同步监视器。语法格式如下:

synchronized(obj) {

……

}

示例代码,模拟多个用户对同一个账户的取钱操作:

   1: //当多条线程修改同一共享数据时, 将涉及到线程安全
   2:     public void run() {
   3:         synchronized(account) {
   4:             //账户余额大于期望取到的金额
   5:             if (account.getBalance() >= drawAmount) {
   6:                 //吐抄
   7:                 System.out.println(getName() + "取钱成功,突出钞票:" + drawAmount);
   8:                 
   9:                 //修改余额
  10:                 account.setBalance(account.getBalance() - drawAmount);
  11:                 System.out.println("\t余额为:" + account.getBalance());
  12:             }
  13:             else {
  14:                 System.out.println("余额不足,取钱失败!");
  15:             }
  16:         }
  17:         
  18:     }

第二种:同步方法

同步方法可以看作是同步代码块的变体,他不需要显示指定同步监视器,不过实则是把自己this当作同步监视器,因此而知同步方法是定义在要操作类的内部。示例代码,同样模拟取钱操作:

   1: package org.frzh.thread;
   2:  
   3: public class Account2 {
   4:     private String accountNo;
   5:     private double balance;
   6:     
   7:     public Account2() {}
   8:     public Account2(String accountNo, double balance) {
   9:         this.accountNo = accountNo;
  10:         this.balance = balance;
  11:     }
  12:     
  13:     public double getBalance() {
  14:         return this.balance;
  15:     }
  16:     //线程安全方法
  17:     public synchronized void draw(double drawAmount) {
  18:         //账户余额大于期望取到的金额
  19:         if (this.balance >= drawAmount) {
  20:             //吐抄
  21:             System.out.println(Thread.currentThread().getName() + "取钱成功,突出钞票:" + drawAmount);
  22:             
  23:             //修改余额
  24:             this.balance -= drawAmount;
  25:             System.out.println("\t余额为:" + this.balance);
  26:         }
  27:         else {
  28:             System.out.println("余额不足,取钱失败!");
  29:         }
  30:     }
  31: }

同步方法和同步代码库比较而言,同步方法更符合面向对象编程的思想。

第三种:同步锁(Lock)

同步锁是在线程访问共享资源时将资源锁定,此时不允许其他线程对共享资源的访问,操作完成之后再释放同步锁(且必须显示调用)。相比较同步代码块和同步方法而言,同步锁显得更加灵活,当然使用起来也是最容易出粗的。示例代码:

   1: package org.frzh.thread;
   2:  
   3: import java.util.concurrent.locks.ReentrantLock;
   4:  
   5: public class Account3 {
   6:     //定义所对象
   7:     private final ReentrantLock lock = new ReentrantLock();    //可重入锁
   8:     private String accountNo;
   9:     private double balance;
  10:     
  11:     public Account3() {}
  12:     public Account3(String accountNo, double balance) {
  13:         this.accountNo = accountNo;
  14:         this.balance = balance;
  15:     }
  16:     
  17:     public double getBalance() {
  18:         return this.balance;
  19:     }
  20:     
  21:     public void draw(double drawAmount) {
  22:         lock.lock();
  23:         try {
  24:             //账户余额大于期望取到的金额
  25:             if (this.balance >= drawAmount) {
  26:                 //吐抄
  27:                 System.out.println(Thread.currentThread().getName() + "取钱成功,突出钞票:" + drawAmount);
  28:                 
  29:                 //修改余额
  30:                 this.balance -= drawAmount;
  31:                 System.out.println("\t余额为:" + this.balance);
  32:             }
  33:             else {
  34:                 System.out.println("余额不足,取钱失败!");
  35:             }
  36:         } finally {
  37:             lock.unlock();
  38:         }
  39:     }
  40: }