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

标签 java multithreading queue java.util.concurrent

Q1)我创建了一个基于链表的数据库连接池实现。需要连接的线程 poll() 从列表中获取连接,线程使用 add() 或 addFirst() 释放连接。在测试过程中,我注意到,即使一个线程使用synchronized(ll) {这里有一些代码}锁定了列表,其他线程也能够从列表中 poll() 出连接。这个测试让我得出结论,只有 {} 中的代码块才能保证一次由 1 个线程执行,但对象本身(即 ll )不会被锁定,其他线程仍然可以在其上写入。那是对的吗 ??那把ll当monitor有什么用呢?我也可以使用同步(this)..

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

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

最佳答案

好的,你有一些 list :

LinkedList ll = ...;

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

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

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

同步某些数据结构(例如链表)的原因是,当一个线程必须创建临时无效状态才能完成其工作时,防止其他线程看到该结构处于无效状态。

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

<小时/>

这是没有用的,因为永远不会允许其他线程在ll上同步:

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

您通常希望保持同步块(synchronized block)尽可能短:您希望代码快速进入和退出,以最大限度地减少其他线程等待轮到的时间。

关于java - synchronized 关键字没有锁定链表,其他线程仍在从中轮询对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35694696/

相关文章:

java - 如何使用ehcache或JCS作为队列或流式缓存?

queue - 禁用 TeamCity 构建队列

java - 不同 ListView 项的不同选择颜色

java - java中带有自定义对象的列表的深拷贝

java - 对象级锁定是线程安全的吗?

.net - 来自 Prometheus .NET 客户端库的 Metrics 实例是线程安全的吗

c++ - 这个入队功能是如何工作的?

java - byte[] 到 Java 中的文件

java - 关于聚合消息

c# - 确保从不同的读取线程看到写入