Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何相互排除两个程序段_Java_Multithreading_Concurrency - Fatal编程技术网

Java 如何相互排除两个程序段

Java 如何相互排除两个程序段,java,multithreading,concurrency,Java,Multithreading,Concurrency,我有以下Java并发问题: 有两个函数,f1和f2,可以由任何线程以任意顺序执行 允许多个线程同时执行f1 允许多个线程同时执行f2 如果至少有一个线程正在执行f2,则不允许任何线程执行f1,反之亦然,如果f2 现在,简单(次优)的实现是: class AccessedByManyThreads { void doActionWithF1() { foo(); synchronized (this) { f1(); } bar(); } v

我有以下Java并发问题:

  • 有两个函数,f1f2,可以由任何线程以任意顺序执行
  • 允许多个线程同时执行f1
  • 允许多个线程同时执行f2
  • 如果至少有一个线程正在执行f2,则不允许任何线程执行f1,反之亦然,如果f2
  • 现在,简单(次优)的实现是:

    class AccessedByManyThreads {
      void doActionWithF1() {
        foo();
        synchronized (this) {
          f1();
        }
        bar();
      }
      void doActionWithF2() {
        baz();
        synchronized (this) {
          f2();
        }
        faz();
      }
    }
    
    此实现满足需求4,但它不利用需求2允许的松弛。三,。实际上,我需要像ReadWriteLock这样的东西,在这里不仅可以共享读锁,还可以共享写锁

    所以我的问题是:

  • 是否有任何Java并发库原语可以用来满足需求2。和3
  • 如果没有,实施的想法是什么

  • 我不确定是否有任何Java并发库在这个用例中会有所帮助。但是,您可以模拟类似于信号量变量的内容来实现这一点:

    class AccessedByManyThreads {
        private int threadsAccessingF1;
        private int threadsAccessingF2;
    
        public AccessedByManyThreads() {
            this.threadsAccessingF1 = 0;
            this.threadsAccessingF2 = 0;
        }
    
        public void doActionWithF1() {
            synchronized(this) {
                if(threadsAccessingF2 > 0) {
                    return;    
                    // some function(s) are accessing f2, so return without calling f1()
                }
                else {
                    threadsAccessingF1++;
                }
            }
            f1();
            synchronized(this) {
                threadsAccessingF1--;
            }
        }
    
        public void doActionWithF2() {
            synchronized(this) {
                if(threadsAccessingF1 > 0) {
                    return;    
                    // some function(s) are accessing f1, so return without calling f2()
                }
                else {
                    threadsAccessingF2++;
                }
            }
            f2();
            synchronized(this) {
                threadsAccessingF2--;
            }
        }
    }
    

    我不确定是否有任何Java并发库在这个用例中会有所帮助。但是,您可以模拟类似于信号量变量的内容来实现这一点:

    class AccessedByManyThreads {
        private int threadsAccessingF1;
        private int threadsAccessingF2;
    
        public AccessedByManyThreads() {
            this.threadsAccessingF1 = 0;
            this.threadsAccessingF2 = 0;
        }
    
        public void doActionWithF1() {
            synchronized(this) {
                if(threadsAccessingF2 > 0) {
                    return;    
                    // some function(s) are accessing f2, so return without calling f1()
                }
                else {
                    threadsAccessingF1++;
                }
            }
            f1();
            synchronized(this) {
                threadsAccessingF1--;
            }
        }
    
        public void doActionWithF2() {
            synchronized(this) {
                if(threadsAccessingF1 > 0) {
                    return;    
                    // some function(s) are accessing f1, so return without calling f2()
                }
                else {
                    threadsAccessingF2++;
                }
            }
            f2();
            synchronized(this) {
                threadsAccessingF2--;
            }
        }
    }
    
  • 我不认为有一个标准的库类可以帮助你开箱即用

  • 解决方案:

  • 这种情况类似于十字路口,f1和f2是两条相交的道路。交通信号灯将允许f1或f2的车辆通过,但绝不允许两者同时通过。我在过去遇到过这样的问题,然后构建了这个同步器类:

    public class TrafficLight<T> {
    
        private ReentrantLock lock = new ReentrantLock(true);
        private Condition switched = lock.newCondition();
        private int registered;
        private int maxBeforeYield = 20;
        private T state;
    
        public void acquire(T t) throws InterruptedException {
            lock.lock();
            try {
                while ((state != null && !state.equals(t)) || maxBeforeYield == 0) {
                    switched.await();
                }
                if (state == null) {
                    state = t;
                }
                registered++;
                maxBeforeYield--;
            } finally {
                lock.unlock();
            }
        }
    
        public void release() {
            lock.lock();
            try {
                registered--;
                if (registered == 0) {
                    state = null;
                    maxBeforeYield = 20;
                    switched.signalAll();
                }
            } finally {
                lock.unlock();
            }
        }
    }
    
    公共级交通灯{
    private ReentrantLock lock=new ReentrantLock(true);
    私有条件切换=lock.newCondition();
    私人注册;
    private int maxBeforeYield=20;
    私有的T型国家;
    公共无效获取(T T)抛出中断异常{
    lock.lock();
    试一试{
    while((state!=null&&!state.equals(t))| | maxBeforeYield==0){
    switched.wait();
    }
    if(state==null){
    状态=t;
    }
    注册++;
    最大收益率--;
    }最后{
    lock.unlock();
    }
    }
    公开无效释放(){
    lock.lock();
    试一试{
    注册--;
    如果(已注册==0){
    state=null;
    maxBeforeYield=20;
    switched.signalAll();
    }
    }最后{
    lock.unlock();
    }
    }
    }
    
    创建trafficLight,并使尝试调用f1()的方法获取状态“f1”,以及尝试调用f2()的方法获取状态“f2”(显然可以使用其他状态对象)

    如前所述,只要20个或更多线程正在等待不同的状态,该类就会强制进行状态切换。这基本上相当于将两个方向都设置为红灯,然后在十字路口通行后将另一个方向设置为绿灯

  • 我不认为有一个标准的库类可以帮助你开箱即用

  • 解决方案:

  • 这种情况类似于十字路口,f1和f2是两条相交的道路。交通信号灯将允许f1或f2的车辆通过,但绝不允许两者同时通过。我在过去遇到过这样的问题,然后构建了这个同步器类:

    public class TrafficLight<T> {
    
        private ReentrantLock lock = new ReentrantLock(true);
        private Condition switched = lock.newCondition();
        private int registered;
        private int maxBeforeYield = 20;
        private T state;
    
        public void acquire(T t) throws InterruptedException {
            lock.lock();
            try {
                while ((state != null && !state.equals(t)) || maxBeforeYield == 0) {
                    switched.await();
                }
                if (state == null) {
                    state = t;
                }
                registered++;
                maxBeforeYield--;
            } finally {
                lock.unlock();
            }
        }
    
        public void release() {
            lock.lock();
            try {
                registered--;
                if (registered == 0) {
                    state = null;
                    maxBeforeYield = 20;
                    switched.signalAll();
                }
            } finally {
                lock.unlock();
            }
        }
    }
    
    公共级交通灯{
    private ReentrantLock lock=new ReentrantLock(true);
    私有条件切换=lock.newCondition();
    私人注册;
    private int maxBeforeYield=20;
    私有的T型国家;
    公共无效获取(T T)抛出中断异常{
    lock.lock();
    试一试{
    while((state!=null&&!state.equals(t))| | maxBeforeYield==0){
    switched.wait();
    }
    if(state==null){
    状态=t;
    }
    注册++;
    最大收益率--;
    }最后{
    lock.unlock();
    }
    }
    公开无效释放(){
    lock.lock();
    试一试{
    注册--;
    如果(已注册==0){
    state=null;
    maxBeforeYield=20;
    switched.signalAll();
    }
    }最后{
    lock.unlock();
    }
    }
    }
    
    创建trafficLight,并使尝试调用f1()的方法获取状态“f1”,以及尝试调用f2()的方法获取状态“f2”(显然可以使用其他状态对象)


    如前所述,只要20个或更多线程正在等待不同的状态,该类就会强制进行状态切换。这基本上相当于将两个方向都设置为红灯,然后在十字路口通行后将另一个方向设置为绿灯。

    您需要它做什么?如果只是用锁定实现规则,那么结果是不稳定的——只要有线程执行F1,就没有人执行F2,反之亦然。您可能需要一个在F1和F2之间切换的策略,该策略需要根据您的实际使用情况进行通知case@MattTimmermans“只要有线程执行F1,就没有人会执行F2”-在我的用例中这很好。我所做的是对f1的突然调用,然后在f2的一段时间之后。然而,它们可以随着时间的推移而被涂抹,但仍然保持着突发性。由于f1(f2)实现的并发性保证,多线程在不锁定的情况下调用f1()(或f2())是可以的,但是由于f1的正确性问题,我不能允许执行f2。您需要它做什么?如果只是通过锁定实现规则,那么结果是不稳定的——只要