两个线程进入Semaphore,如下:
semp.acquire();
System.out.println("Accessing ");
semp.release(); 
请问,有没有可能打印AcceAccessing ssing ,也就是说进入信号量中的线程是互斥的吗?

解决方案 »

  1.   

    楼主,请先解释下什么叫线程互斥,不明白你想问什么。Semaphore应该和你所谓的线程互斥没任何关系,它解决的问题就是保证了同一时间能运行的最大线程数。至于线程之间有什么通信和Semaphore无关也没必要关心。
    引用一下网上的一段话:Semaphore实现的功能就类似厕所有5个坑,假如有10个人要上厕所,那么同时只能有多少个人去上厕所呢?同时只能有5个人能够占用,当5个人中 的任何一个人让开后,其中等待的另外5个人中又有一个人可以占用了。另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项。生产者和消费者模型的概念你完全没搞懂。它本身就是针对多生产者和多消费者的,一个的话没有任何意义。synchronized只是保证了多线程情况下保证每个共享资源能被同步安全地访问(比如保证每张火车票不被卖2次)。而不是说只能有一个线程可以访问。我觉得楼主的学习方法有问题,你要搞清楚某项技术,首先要弄明白这个技术实现的目的是什么,自己先百度了解一下。有了具体疑问再针对性地提问。你的问题显得你学东西太盲目了。
      

  2.   

    2楼不是我的学习方法有问题,可能我没描述明白,我知道Semaphore是控制线程个数的,而且5个厕所坑也很经典,我想问的是,5个线程在享用这5个厕所的时候会不会存在竞争关系,也就是说在一个打印Accessing(蹲坑)的时候,另外一个会不会和他抢(在第一个没打印完,强行自己打印)
      

  3.   


    前面已经说了你这个问题另外一个问题,也就是说和Semaphore没有关系。你把两者关联在一起没有意义,只能误导看问题的人。多线程是否会互斥其实也就是是否需要同步,取决于下面2个需求
    1、这些线程是否会访问共享资源
    2、是否要保证共享资源访问的顺序(类似一张票不能卖2次)
    如果你没有上面2个需求,大家各运行各的,不存在互斥即同步问题。就好像5个窗口同时卖火车票,如果事先约定每个窗口卖的票都不会重复(比如每个窗口卖的是不同的线路),你同步干嘛???如果每个窗口卖的有相同线路的票,那就要保证如果2个窗口同时卖票时不能把一张票卖2次,这时才需要同步,即使用synchronized锁住卖票那段代码。保证一个窗口在卖票的时候加锁,当另一个窗口也想卖票时,synchronized锁会告诉这个窗口,嘿!我正卖着呢,等我卖完了你再卖!当然,如果把所有票都锁住也不合理,实际场景肯定有分而治之锁的策略,这里就不深入讨论了。回到厕所的问题,Semaphore保证只能5个人进厕所,但厕所的蹲坑未必就是5个,也可能是3个,那这5个人就要继续竞争这个3个坑,Semaphore只保证放进厕所5个人,但是否保证这5个人一定同时能有蹲坑就不是它的事了。就要靠synchronized来保证3个蹲坑的资源同步了,否则就会有人打架争蹲坑,而这没有Semaphore的一点责任,而是synchronized的责任。
      

  4.   

    明白了,谢谢二楼回答。也就是会出现AcceAccessingssing这种结果,我测试了很多遍,没有出现上诉情况,我怀疑是不是semaphore自带锁机制。
    package com.thread;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;public class Semaphore1 {
    public static void main(String[] args) {
    // 线程池
     ExecutorService exec = Executors.newCachedThreadPool();
    // 只能5个线程同时访问
    final Semaphore semp = new Semaphore(5);
    // 模拟20个客户端访问
    for (int index = 0; index < 20; index++) {
    final int NO = index;
    Runnable run = new Runnable() {
    public void run() {
    try {
    // 获取许可
    semp.acquire();
    System.out.println("Accessing: " + NO);
    Thread.sleep(1000);
    // 访问完后,释放
    semp.release();
    System.out.println("-----------------"+semp.availablePermits());
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    };
    exec.execute(run);
    }
    // 退出线程池
    exec.shutdown();
    }
    }
    这是测试代码。
    每次打印都是
    Accessing: 0
    Accessing: 1
    ……
    这种可见他们内部并没有征厕所,当然可能是重现不出来。
      

  5.   

    你的代码里没有synchronized或者相关的锁机制代码,自然就没有你说的互斥嘛,说到底你还是不理解synchronized的意义。
    多线程是否会互斥其实也就是是否需要同步,取决于下面2个需求
    1、这些线程是否会访问共享资源
    2、是否要保证共享资源访问的顺序(类似一张票不能卖2次)不要一看见多线程就一定就是会有synchronized,这根本是2个东西。多线程只是提高代码执行效率,充分利用cpu等硬件资源,只有你的需要需要同步,才去人为的写synchronized代码,取决于需求!不要形而上学。