如何实现信号量

时间:2015-11-17 20:54:42

标签: java multithreading semaphore

所以我创建了一个程序,试图显示使用共享变量的危险,因此我有3个类,主要是DangersOfSharedVariablesIncrementerDecrementer

所以我的想法是让两个线程一次运行,同时调用他们尊重的方法,因此Decrementer类将在main中调用decrementShared()方法,Incrementer类将在main中调用incrementShared()方法。

以下是主要方法:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package dangersofsharedvariables;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 */
public class DangersOfSharedVariables {

    /**
     * @param args the command line arguments
     */
    private static int sharedValue =0;
    private static int numberOfCycles = 2000000000;

    public static void main(String[] args) {
        // TODO code application logic here
        Incrementer in = new Incrementer(numberOfCycles);
        Decrementer de = new Decrementer(numberOfCycles);
        Semaphore sem = new Semaphore(1);


        in.start();
        try {
            in.join();
        } catch (InterruptedException ex) {}
        de.start();
        try {
            de.join();
        } catch (InterruptedException ex) {}
        System.out.println(sharedValue);
    }

    public void decrementShared(){
        sharedValue -=10;
    }

    public void incrementShared(){
        sharedValue +=10;
    }

}

这里是Incrementer类

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package dangersofsharedvariables;

/**
 *
 * 
 */
public class Incrementer extends Thread {

    private int numberOfIncrements;

    public Incrementer(int numberOfIncrements) {
        this.numberOfIncrements = numberOfIncrements;

    }

    @Override
    public void run() {
        DangersOfSharedVariables in = new   DangersOfSharedVariables();
        for(int i = 0; i < numberOfIncrements; i++){
            in.incrementShared();
        }
    }
}

Decrementer Class:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package dangersofsharedvariables;

/**
 *
 * 
 */
public class Decrementer extends Thread {
    private int numberOfDecrements;
    public Decrementer(int numberOfDecrements){
        this.numberOfDecrements = numberOfDecrements;

    }

    @Override
    public void run(){
        DangersOfSharedVariables d = new DangersOfSharedVariables();
        for(int i = 0; i < numberOfDecrements; i++){
            d.decrementShared();
        }
    }
}

我正在使用谷歌搜索,更安全的方法是使用Sempaphore类。所以我自己动手使用我找到的信号量模板,但不确定我是如何实现的。

信号量类:

package dangersofsharedvariables;

public class Semaphore {

    // *************************************************************
    // Class properties.
    // Allow for both counting or mutex semaphores.
    private int count;

    // *************************************************************
    // Constructor
    public Semaphore(int n) {
        count = n;
    }

    // *************************************************************
    // Public class methods.
    // Only the standard up and down operators are allowed.
    public synchronized void down() {

        while (count == 0) {

            try {
                wait(); // Blocking call.
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }
        }
        count--;
    }

    public synchronized void up() {
        count++;
        notify();
    }

}

2 个答案:

答案 0 :(得分:1)

你想要的名字是&#34;互斥&#34;这是&#34;互相排斥&#34;的缩写。互斥锁是一个代码块,一次只能由一个线程执行。

Java语言语句synchronized (foo) { ... }实现互斥。 foo是一个表达式,它产生一些对象(有时称为锁定对象),而...是要保护的语句。 Java语言保证不允许两个线程同时synchronize同一个锁对象。

Semaphore可以用来提供相互排斥,但它更加繁琐,而且过时了。

Semaphore是在计算机具有用于线程同步的硬件原语之前发明的。它应该是&#34;原始&#34;可以构建其他同步构造(例如,互斥体)的操作。

今天,Semaphore的Java实现实际上建立在与synchronized语句相同的硬件基元之上。

答案 1 :(得分:1)

根据您的查询,以下是有关semephore数据结构的简要说明。信号量可用于解决各种同步问题。 Dijkstra(1968)引入了这个概念,他将信号量作为操作系统的一部分引入,以便使进程彼此之间以及与硬件同步。

典型信号量的结构包括4个阶段:

  1. 非关键区域
  2. 入境协议
  3. 关键区域
  4. 退出协议
  5. 非关键区域是可以由2-n个线程同时执行的任何代码。

    入口协议是在进入关键区域之前必须由进程执行的代码。它旨在防止进程进入关键区域,如果另一个进程已在使用共享资源。

    关键区域是正在访问共享资源的代码部分。

    退出协议是进程必须在完成其关键区域后立即执行的代码。

    信号量可以用于不同的用途:

    1. 用于对单个共享资源的互斥访问,在这种情况下,信号量称为二进制信号量
    2. 保护对多个资源实例的访问(计算信号量
    3. 同步两个进程(阻塞信号量
    4. 信号量机制的多功能性通过正确的初始化来实现。

      出于演示目的,请参考下面的示例,其中展示了最简单的二进制信号量实现:

      信号量:

      package BinarySemaphore;
      
      public class Semaphore{
          private static Semaphore semaphore;
          private static int resource = 1;
      
          private Semaphore(){}
      
          public synchronized void increment(){
              while(isAvailable()){
                  try {
                      this.wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
              resource += 1;
      
              report();
      
              this.notifyAll();
          }
      
          public synchronized void decrement(){
              while(!isAvailable()){
                  try {
                      this.wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
      
              resource -= 1;
      
              report();
      
              this.notifyAll();
          }
      
          public synchronized final static boolean isAvailable(){
              return resource == 1 ? true : false;
          }
      
          public synchronized final static void report(){
              System.out.println("Resource value: " + resource);
          }
      
          public final static Semaphore getInstance(){
              if(semaphore == null){
                  semaphore = new Semaphore();
              }
              return semaphore;
          }
      }
      

      增量计:

      package semaphore;
      
      import BinarySemaphore.Semaphore;
      
      public class Incrementer implements Runnable{
          private static Semaphore semaphore = null;
      
      public Incrementer(Semaphore s){
          semaphore = s;
      }
      
      @Override
      public void run() {
          for(int i = 0; i < 10; i++){
              System.out.println("Incrementing...");
              semaphore.increment();
          }
      }
      

      }

      Decrementer:

      package semaphore;
      
      import BinarySemaphore.Semaphore;
      
      public class Decrementer implements Runnable{
          private static Semaphore semaphore = null;
      
          public Decrementer(Semaphore s) {
              semaphore = s;
          }
      
          @Override
          public void run() {
              for(int i = 0; i < 10; i++){
                  System.out.println("Decrementing...");
                  semaphore.decrement();
              }
          }
      }
      

      主要:

      package semaphore;
      
      import BinarySemaphore.Semaphore;
      
      public class Main {
          public static void main(String[] args){
              Thread iIncrement = new Thread(new Incrementer(Semaphore.getInstance()));
              Thread iDecrement = new Thread(new Decrementer(Semaphore.getInstance()));
      
              iIncrement.start();
              iDecrement.start();
          }
      }
      

      输出

      Decrementing...
      Incrementing...
      Resource value: 0
      Decrementing...
      Resource value: 1
      Incrementing...
      Resource value: 0
      Decrementing...
      Resource value: 1
      Incrementing...
      Resource value: 0
      Decrementing...
      Resource value: 1
      Incrementing...
      Resource value: 0
      Decrementing...
      Resource value: 1
      Incrementing...
      Resource value: 0
      Decrementing...
      Resource value: 1
      Incrementing...
      Resource value: 0
      Decrementing...
      Resource value: 1
      Incrementing...
      Resource value: 0
      Decrementing...
      Resource value: 1
      Incrementing...
      Resource value: 0
      Decrementing...
      Resource value: 1
      Incrementing...
      Resource value: 0
      Decrementing...
      Resource value: 1
      Incrementing...
      Resource value: 0
      Resource value: 1