Java多线程同步设计中使用Metux

Mutex是互斥体,广泛地应用在多线程编程中。本文以广为流程的Doug Lea的concurrent工具包的Mutex实现为例,进行一点探讨。在Doug Lea的concurrent工具包中,Mutex实现了Sync接口,该接口是concurrent工具包中所有锁(lock)、门(gate)和条件变量(condition)的公共接口,Sync的实现类主要有:Mutex、Semaphore及其子类、Latch、CountDown、ReentrantLock等。这也体现了面向抽象编程的思想,使我们可以在不改变代码或者改变少量代码的情况下,选择使用Sync的不同实现。下面是Sync接口的定义:

public interface Sync
{
  public void acquire() throws InterruptedException;
  //获取许可
  public boolean attempt(long msecs) throws InterruptedException;
  //尝试获取许可
  public void release();
  //释放许可
}


通过使用Sync可以替代Java synchronized关键字,并提供更加灵活的同步控制。当然,并不是说 concurrent工具包是和Java synchronized独立的技术,其实concurrent工具包也是在synchronized的基础上搭建的,从下面对Mutex源码的解析即可以看到这一点。synchronized关键字仅在方法内或者代码块内有效,而使用Sync却可以跨越方法甚至通过在对象之间传递,跨越对象进行同步。这是Sync及concurrent工具包比直接使用synchronized更加强大的地方。

注意Sync中的acquire()和attempt()都会抛出InterruptedException,所以使用Sync及其子类时,调用这些方法一定要捕获InterruptedException。而release()方法并不会抛出InterruptedException,这是因为在acquire()和attempt()方法中可能会调用wait()等待其它线程释放锁。而release()在实现上进行了简化,直接释放锁,不管是否真的持有。所以,你可以对一个并没有acquire()的线程调用release()这也不会有什么问题。而由于release()不会抛出InterruptedException,所以我们可以在catch或finally子句中调用release()以保证获得的锁能够被正确释放。比如:

class X
{
  Sync gate; // ...
  public void m()
  {
   try
   {
    gate.acquire();
    // block until condition holds
    try
    {
     // ... method body
    }
    finally { gate.release(); }
   }
   catch (InterruptedException ex) { // ... evasive action }
  }
}


Mutex是一个非重入的互斥锁。Mutex广泛地用在需要跨越方法的before/after类型的同步环境中。下面是Doug Lea的concurrent工具包中的Mutex的实现。

public class Mutex implements Sync
{
  /** The lock status **/
  protected boolean inuse_ = false;
  public void acquire() throws InterruptedException
  {
   if (Thread.interrupted()) throw new InterruptedException();//(1)
   synchronized(this)
   {
    try
    {
     while (inuse_) wait();
     inuse_ = true;
    }
    catch (InterruptedException ex)
    {
     //(2)
     notify();
     throw ex;
    }
   }
  }
  public synchronized void release()
  {
   inuse_ = false;
   notify();
  }
  public boolean attempt(long msecs) throws InterruptedException
  {
   if (Thread.interrupted()) throw new InterruptedException();
   synchronized(this)
   {
    if (!inuse_)
    {
     inuse_ = true;
     return true;
    }
    else if (msecs <= 0)
     return false;
    else
    {
     long waitTime = msecs;
     long start = System.currentTimeMillis();
     try
     {
      for (;;)
      {
       wait(waitTime);
       if (!inuse_)
       {
        inuse_ = true;
        return true;
       }
       else
       {
        waitTime = msecs - (System.currentTimeMillis() - start);
        if (waitTime <= 0) // (3)
         return false;
       }
      }
     }
     catch (InterruptedException ex)
     {
      notify();
      throw ex;
     }
    }
   }
  }
}

时间: 2024-07-31 03:12:19

Java多线程同步设计中使用Metux的相关文章

Java多线程同步问题的探究(一、线程的先来后到)

众所周知,在Java多线程编程中,一个非常重要的方面就是线程的同步问题. 关于线程的同步,一般有以下解决方法: 1. 在需要同步的方法的方法签名中加入synchronized关键字. 2. 使用synchronized块对需要进行同步的代码段进行同步. 3. 使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象. 另外,为了解决多个线程对同一变量进行访问时可能发生的安全性问题,我们不仅可以采用同步机制,更可以通过JDK 1.2中加入的 ThreadLocal

ava 同步-Java 多线程同步工具 CyclicBarrier

问题描述 Java 多线程同步工具 CyclicBarrier Java中使用CyclicBarrier控制多个线程在执行完后,才执行后续操作,请大家帮我分析下,项目两个代码中为什么执行结果不一样: 代码1. public class CyclicBarrierTest2 { public static void main(String[] args) throws InterruptedException, BrokenBarrierException { final CyclicBarrie

java多线程-同步块实例讲解_java

java多线程-同步块 Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java 同步块用来避免竞争.本文介绍以下内容: Java 同步关键字(synchronzied) 实例方法同步 静态方法同步 实例方法中同步块 静态方法中同步块 Java 同步示例 Java 同步关键字(synchronized) Java 中的同步块用 synchronized 标记.同步块在 Java 中是同步在某个对象上.所有同步在一个对象上的同步块在同时只能被一个线程进入并执

java多线程同步问题,小弟百撕不得其解,特来求助!

问题描述 java多线程同步问题,小弟百撕不得其解,特来求助! 多线程共享同一资源,同一张票卖出了多张!同步方法,同步代码块都没用. 问题:编写三各类Ticket.SealWindow.TicketSealCenter分别代表票信息.售票窗口.售票中心.售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程. public class ThreadDemo { public static void main(String[] args) { Thread t1

java多线程同步的问题

问题描述 java多线程同步的问题 小测试,如何实现变量ticket的同步 private int ticket = 100; public void run() { while(ticket > 0 ) { System.out.println(ticket+" is saled by "+ Thread.currentThread().getName()); ticket--; try { Thread.sleep(200); } catch (InterruptedExce

Java多线程同步中的两个特殊类

Java语言内置了synchronized关键字用于对多线程进行同步,大大方便了Java中多线程程序的编写.但是仅仅使用synchronized关键字还不能满足对多线程进行同步的所有需要.大家知道,synchronized仅仅能够对方法或者代码块进行同步,如果我们一个应用需要跨越多个方法进行同步,synchroinzed就不能胜任了.在C++中有很多同步机制,比如信号量.互斥体.临届区等.在Java中也可以在synchronized语言特性的基础上,在更高层次构建这样的同步工具,以方便我们的使用

Java多线程同步问题的探究(三、Lock来了,大家都让开【1.认识重入锁】)

在上一节中,我们已经了解了Java多线程编程中常用的关键字synchronized,以及与之相关的对象锁机制.这一节中,让我们一起来认 识JDK 5中新引入的并发框架中的锁机制. 我想很多购买了<Java程序员面试宝典>之类图书的朋友一定对下面这个面试题感到非常熟悉: 问:请对比synchronized与java.util.concurrent.locks.Lock 的异同. 答案:主要相同点:Lock能完成synchronized所实现的所有功能 主要不同点:Lock有比synchroniz

Java多线程同步问题的探究(二、给我一把锁,我能创造一个规矩)

在上一篇中,我们讲到了多线程是如何处理共享资源的,以及保证他们对资源进行互斥访问所依赖的重要机制:对象锁. 本篇中,我们来看一看传统的同步实现方式以及这背后的原理. 很多人都知道,在Java多线程编程中,有一个重要的关键字,synchronized.但是很多人看到这个东西会感到困惑:"都说同步机制是 通过对象锁来实现的,但是这么一个关键字,我也看不出来Java程序锁住了哪个对象阿?" 没错,我一开始也是对这个问题感到困惑和不解.不过还好,我们有下面的这个例程: 1 public cla

Java多线程同步问题的探究(四)

四.协作,互斥下的协作--Java多线程协作(wait.notify.notifyAll) Java监视器支持两种线程:互斥和协作. 前面我们介绍了采用对象锁和重入锁来实现的互斥.这一篇中,我们来看一看线程的协作. 举个例子:有一家汉堡店举办吃汉堡比赛,决赛时有3个顾客来吃,3个厨师来做,一个服务员负责协调汉堡的数量.为了避免浪费,制 作好的汉堡被放进一个能装有10个汉堡的长条状容器中,按照先进先出的原则取汉堡.如果容器被装满,则厨师停止做汉堡,如果顾客发 现容器内的汉堡吃完了,就可以拍响容器上