【问题标题】:Java:Multiple thread safety issues: Using Thread extends and LockJava:多线程安全问题:使用线程扩展和锁定
【发布时间】:2021-01-27 02:37:29
【问题描述】:

当我使用Thread类和Lock解决线程安全问题时,出现0票!

代码:

package ThreadTest;

import java.util.concurrent.locks.ReentrantLock;

class ThreadOne extends Thread{
    private static int ticket = 100;
    private ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while(true){
            try {
                lock.lock();
                if(ticket > 0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"selling ticket: "+ticket);
                    ticket--;
                }else{
                    break;
                }
            } finally {
                lock.unlock();
            }
        }
    }
}

public class ThreadMethod {
    public static void main(String[] args) {
        ThreadOne t1 = new ThreadOne();
        ThreadOne t2 = new ThreadOne();

        t1.setName("Window 1:");
        t2.setName("Window 2:");

        t1.start();
        t2.start();
    }
}

结果包含: 窗口二:售票:3 窗口一:售票:2 窗口二:售票:1 窗口一:售票:0

0 票!

【问题讨论】:

  • 所以你的意思是我们不能同时使用Thread extends和Lock?
  • 您在每个线程上使用单独的锁。我认为线程必须共享相同的锁对象才能做到这一点。
  • 我知道这与您的问题无关,但我建议您考虑实现 Runnable 接口而不是扩展 Thread:stackoverflow.com/q/541487/42962
  • 对,您将lock 声明为实例变量。这意味着每个ThreadOne 都有自己的锁副本,因此它实际上什么也不锁。尝试将锁声明为static
  • 非常感谢!你们的 cmets 帮了我很多!

标签: java multithreading concurrency reentrantlock


【解决方案1】:

第一个问题是每个ThreadOne 实例都有两个独立 锁,因此您实际上并没有锁定任何东西。甚至尝试获取线程之间的锁都没有竞争,因为它们都有自己的锁。如果你这样做ReentrantLockstatic,这很容易解决。

如果您确实做到了static,您会注意到只有一个“窗口”会继续获得门票。这与ReentrantLock 在内部工作的方式以及您使用while(true){...} 的事实有关。这也很容易解决。要么:

  • 换锁公平:private static ReentrantLock LOCK = new ReentrantLock(true);

  • 或者在 finally 块之后休眠一下,让其他线程有机会运行。

像这样:

.....

} finally {
   LOCK.unlock();
}
        
try {
    Thread.sleep(10);
}
catch (InterruptedException e) {
    e.printStackTrace();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 2020-08-28
    • 2018-04-08
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    相关资源
    最近更新 更多