【问题标题】:Little confused about Semaphore Class对信号量类有点困惑
【发布时间】:2013-12-18 15:45:11
【问题描述】:

我对 java.util.concurrent 包中的“Semaphore”类有点困惑。这是我的代码 sn-p:

import java.util.concurrent.Semaphore;

public class TestSemaphore {
    public static void main(String[] args){
        Semaphore limit = new Semaphore(2);
        SemaphoreAA s = new SemaphoreAA(limit);
        AAThread a = new AAThread(s);
        Thread[] sThread = new Thread[100];
        for(int i = 0; i<100; i++){
            sThread[i] = new Thread(a,"[sThread"+i+"]");
            sThread[i].start();

        }
    }
}

class SemaphoreAA{
    private static int counter;
    private Semaphore limit;

    public SemaphoreAA(Semaphore limit){
        this.limit = limit;
    }

    public void increment() throws InterruptedException{
        System.out.printf("%-15s%-25s%5d%n",Thread.currentThread().getName()," : Before Increment. Current counter: ",counter);
        limit.acquire();
        System.out.printf("%-15s%-25s%n",Thread.currentThread().getName()," : Get the resource. Start to increment.");
        counter++;
        System.out.printf("%-20s%-40s%5d%n",Thread.currentThread().getName()," : Increment is done. Current counter: ",counter );
        limit.release();
    }
}

class AAThread implements Runnable{
    private SemaphoreAA s;

    public AAThread(SemaphoreAA s){
        this.s = s;

    }

    public void run() {
        try {
            s.increment();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

我知道它可以用来控制对资源的访问。如果我将限制设置为一个,例如“Semaphore limit = new Semaphore(1);”,它看起来就像一个锁。事实证明。如果我将限制设置为两个,我希望在给定时间内有两个线程可以访问 increment() 方法,这可能会导致数据竞争。输出可能是这样的:

  • [sThread3]:增量之前。当前计数器:2
  • [sThread4]:增量之前。当前计数器:2
  • [sThread3]:获取资源。开始递增。
  • [sThread4]:获取资源。开始递增。
  • [sThread3]:增量完成。当前计数器:3
  • [sThread4]:增量完成。当前计数器:3

但是,虽然我尝试了几次,但都没有出现预期的结果。所以我想知道我是否误解了它。谢谢。

【问题讨论】:

  • 您应该将循环放在 run() 方法中 - 启动线程需要时间并减少交错的可能性...
  • 它在一个线程中@assylias
  • @RamonBoza 每个线程只运行一条指令s.increment(),因此启动线程的时间实际上比increment 的时间长得多——为了有机会观察交错和竞速,你需要及时拨打increment。例如在每个线程中调用increment 10000 次。

标签: java multithreading semaphore


【解决方案1】:

你没看错。

但是,虽然我尝试了几次,但都没有出现预期的结果。

仅仅因为它可以出现并不意味着它会出现。这是大多数并发错误的问题:它们有时会出现,有时不会。

如果您想增加出错的可能性,您可以增加Threads 的数量或在两个不同的循环中创建/启动它们。

【讨论】:

  • 我知道了,这就是为什么我尝试了几次并将线程数增加到 100(而不是 10)以捕获预期结果的原因。但是,它没有用。
  • @franksunn 尝试在递增之前将值分配给局部变量,然后执行if(local + 1 != counter) { fail(); } 在这种情况下,您可以一遍又一遍地运行它,直到它最终失败。
  • 同时删除System.out.println,因为它添加了可能影响您结果的额外同步点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 2017-08-18
  • 2013-06-19
  • 2011-07-10
  • 2013-11-14
  • 1970-01-01
相关资源
最近更新 更多