Java多线程独占访问列表

时间:2017-04-30 00:04:32

标签: java multithreading

我正在进入java多线程,并决定解决一个更复杂的问题,但到目前为止收效甚微。

我有一个工人生产线,他们会尝试从列表中获取工作(创建产品):

  • 我正在使用执行程序来生成工作线程;
  • 每个产品创建意味着完成一组任务;
  • 每个任务都有一个相关的时间,它需要一个资源:需要对每个资源进行独占访问,这意味着在同时创建两个产品时不可能使用它。

使用notify-wait:

解决了对工作列表的并发访问
public class ProductionRequestQueue extends LinkedList<ProductionRequest> {

public ProductionRequestQueue() {
}

public synchronized void push(ProductionRequest productionRequest) {
    this.add(productionRequest);
    notifyAll();
}

public synchronized ProductionRequest pull() {
    while (this.size() == 0) {
        try {
            wait();
        } catch (InterruptedException e) {
        }
    }
    return this.removeFirst();
}}

问题是我需要保证对资源的独占访问权限。我有生产线中可用资源的列表,但我需要保证自己访问资源而不是列表。 我的工人做了:

public Product createProduct(ProductionRequest productionRequest) {
    Product product = ProductionLine.products.get(productionRequest.getProductId());
    product.create();
    return product;
}

@Override
public void run() {
    ProductionRequest productionRequest;
    while (!productionRequestQueue.isEmpty()) {
        productionRequest = productionRequestQueue.pull();
        createProduct(productionRequest);
        System.out.println(productionRequest + " is being manufactured by " + this);
    }
}

然后我有一个将资源与时间联系起来的类,它通过休眠线程来模拟生产过程:

public ResourceTime(Resource resource, int time) {
    this.resource = resource;
    this.time = time;
}

public void execute() {
    synchronized (this.resource) {
        Thread thread = new Thread(this);
        thread.start();
    }
}

@Override
public void run() {
    try {
        System.out.println(toString());
        Thread.sleep(Integer.valueOf(time));
    } catch (NumberFormatException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

我认为同步块可以保证对资源的独占访问,但我不断获得空指针异常:

Exception in thread "pool-1-thread-2" java.lang.NullPointerException
at production_line_sim.models.Worker.createProduct(Worker.java:14)
Any thoughts about this?

另外,我如何证明synchronized块保证对每个资源的独占访问? 我认为这种解决方案可能会导致一些线程可能无法访问资源,并且可能需要某种公平算法,有人可以指出我如何做到这一点吗?

1 个答案:

答案 0 :(得分:3)

首先,我想强调@ pvg的建议:

  

实际上,您最好不要使用标准库。概念是更高层次的,而且这些东西都有效。从基元重新实现这些和/或直接使用基元通常是错误的。如果你想获得一个理解,java.util.concurrent的源代码是可用的,Doug Lea的书仍然是一个有用的参考。

你说你已经解决了NPE问题。

  

另外,我如何证明synchronized块保证对每个资源的独占访问?

synchronized块将为您提供使用等效块的线程之间的独占访问权限。但是,如果您的代码库包含任何代码,该代码在该资源上使用Resource synchronized实例,则存在非独占访问的风险,竞争条件和记忆异常。

您如何找到这样的代码(违反规则)?

  1. 代码检查
  2. 寻找并发危险的静态分析工具。 (我不能推荐一个......)
  3.   

    我认为这种解决方案可能导致某些线程可能无法访问资源的情况,并且可能需要某种公平算法,有人可以指出我如何做到这一点吗?

    公平始终是一个潜在的问题,但通常我们会忽略它。

    一个更真实的问题......你不能忽视......是僵局。在您的情况下,考虑您需要2个或更多资源&#34;创造一个&#34;产品&#34;。假设你有两个工人A和B,它们执行以下操作:

    Worker A: synchronize R1
        Worker A: synchronize R2
    
    Worker B: synchronize R2
        Worker B: synchronize R1
    

    如果这两个序列同时发生,你最终可能会有A等待B释放R2而B等待A释放R1。

    有解决这个问题的策略:

    1. 通过安排工作人员以相同的顺序获取资源锁来避免它。
    2. 死锁检测。例如,工人外部的某些事情注意到当工人陷入僵局时,他们中断了其中一个(或类似的)。 (但是,要小心活锁......)