synchronized关键字没有锁定链表,而其他线程仍在轮询其中的对象

时间:2016-02-29 08:16:05

标签: java multithreading queue java.util.concurrent

Q1)我创建了一个基于链表的数据库连接池实现。需要连接poll()的线程从列表和线程释放连接使用add()或addFirst()。在测试期间,我注意到即使一个线程使用synchronized(ll){some code here}锁定了列表,其他线程也可以从列表中轮询()抛出连接。这个测试让我得出结论,只有{}中的代码块才能保证一次由1个线程执行,但是对象本身即ll,不会被锁定而其他线程仍然可以在其上写入。那是对的吗 ??然后将ll用作监视器的用途是什么?我也可以使用synchronized(this)..

Q2)如果我在创建List期间使用Collections.synchronizedList()创建链接列表作为线程安全,那么我可以摆脱同步块。假设我有两种单独的方法来获得连接和释放连接。目前,这两种方法都使用synchronized块来获取/释放连接。

Q3)如果我决定使用非阻塞列表,例如ConcurrentLinkedQueue(我们有JDK 1.5),这对我们的情况有帮助。我们的峰值连接使用率是30但我们没有对代码施加任何限制,因此连接可以无限增长。我们计划编写一个Timer Task,它将在夜间运行并关闭列表头部的一些连接(旧连接),但是为了执行业务逻辑,我们更愿意使用队列尾部的连接,因为这些是最新发布的连接,以便有非陈旧连接的机会很高。但由于它是一个fifo队列所以我不能从队列的尾部轮询()数据,所以我被迫从队列头部使用可能过时的连接。基本上我需要的是用于执行业务逻辑的堆栈功能,但是用于实现计时器任务的队列功能。您可以建议的任何数据结构。

2 个答案:

答案 0 :(得分:1)

好的,你有一些清单:

LinkedList ll = ...;

ll上同步阻止其他线程访问列表或修改列表:

synchronized(ll) {
    ...protected code...
    // This does NOT prevent other threads from examining or updating
    // ll while the protected code runs.
}

synchronized阻止唯一阻止的是,它阻止其他线程同时在同一个对象上同步。

同步某些数据结构(如链接列表)的原因是为了防止其他线程在一个线程必须创建该临时无效状态以便执行其工作时将结构视为无效状态。

为了使其工作,必须同步创建临时错误状态的代码块,并且必须在同一对象上同步必须防止看到错误状态的每个代码块。

这没用,因为ll

public void run() {
    synchronized(ll) {
        while(true) {
            ...
        }
    }
}

您通常希望尽可能缩短synchronized块:您希望代码能够快速进入并快速离开,以最大限度地减少其他线程等待轮到他们的时间。

答案 1 :(得分:0)

同步不会锁定对象。它锁定在同一对象上同步的代码片段。如果其他代码片段在没有同步的情况下使用同一个对象,它们将继续进行。