当前位置: 首页 > 知识库问答 >
问题:

synchroniz 关键字未锁定链表,其他线程仍在从中轮询对象

翁和正
2023-03-14

Q1) 我创建了一个基于链表的数据库连接池实现。需要连接轮询()的线程从列表中,线程使用add()或adfirst()发布连接。在测试过程中,我注意到即使一个线程使用supgered(ll){此处的一些代码}锁定了列表,其他线程也能够从列表中轮询()出连接。这个测试让我得出结论,只有{}中的代码块将保证一次由1个线程执行,但对象本身(即ll)不会被锁定,其他线程仍然可以在上面写入。这是对的吗?那么把ll作为监视器有什么用?我也可以使用同步(这个)。

Q2)如果我在链表的创建过程中使用Collections.synchronizedList()创建一个线程安全的链表,那么我可以去掉同步块吗?假设我有两种不同的方法来获得连接和释放连接。目前,这两种方法都使用同步块来获取/释放连接。

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

共有2个答案

萧星火
2023-03-14

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

司寇烨伟
2023-03-14

好的,您有一些列表:

LinkedList ll = ...;

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

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

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

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

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

这是没有用的,因为不允许其他线程在< code>ll上同步:

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

您通常希望保持< code>synchronized块尽可能短:您希望代码能够快速进入和退出,以最大限度地减少其他线程等待的时间。

 类似资料:
  • 现在当这个程序运行时,我得到以下输出: 现在我知道这个问题以前已经被问过很多次了,但是有什么方法可以强制解锁互斥锁吗?似乎该实现只允许锁互斥体的线程在主动检查时解锁互斥体,即使使用普通互斥体类型也是如此。 我为什么要这么做?它与编写一个防弹网络服务器有关,该服务器能够从大多数错误中恢复,包括线程意外终止的错误。在这一点上,我看不到从不同于锁定互斥体的线程解锁互斥体的方法。所以在我看来,我有几个选择

  • 问题内容: 我想要一个布尔值来通知系统的某些部分特定服务已启动。 由于某些奇怪的原因,我得到了错误。 奇怪的是notifyAll()在一个同步块内,该块控制着我调用notifyAll()的对象。 我的课是这样开始的: 我正在开发一个android应用程序。我认为它不会影响任何事情,但是我会在注释中补充这个问题,以防影响Java的工作方式。 如果对象锁定在同步块中,为什么会出现异常? 问题答案: 线

  • 我有一个大型Maven多模块项目构建。我将使用PowerMock和Jacoco0.7.8以及离线检测从所有测试开始。 尽管这些被称为“单元测试”,但对一个模块中的类的测试确实会调用其他模块中的重要代码。因此,当我们查看生成的报告时,我们看到了与测试相同的模块中的类的复盖率,但我们看不到测试期间执行的其他模块中的类的复盖率。 我的假设是,如果我能够将其更改为使用在线检测,那么得到的覆盖率报告将包括来

  • 问题内容: 我正在用Go编写执行大量并行计算的软件。我想从工作线程中收集数据,但我不太确定如何以安全的方式进行数据收集。我知道我可以使用通道,但是在我的场景中,它们使它变得更加复杂,因为我必须以某种方式同步主线程中的消息(等到每个线程发送了一些东西)。 情境 主线程创建 n个 实例,并在goroutine中启动其方法,以便每个工作线程都在各自的线程中运行。主线程每10秒应从工作线程中收集一些简单值

  • 问题内容: 我有一个Web应用程序,并且正在使用Oracle数据库,并且有一种基本上像这样的方法: 现在没有任何类型的同步,因此n个线程当然可以自由地访问此方法,当2个线程都进入此方法都进行检查并且当然还没有任何东西时,就会出现问题,然后它们都可以提交事务并创建一个重复的对象。 我不想在数据库中使用唯一的密钥标识符来解决此问题,因为我认为我不应该抓住它。 我也不能在提交之前进行检查,因为不仅要进行

  • 问题内容: 以下函数在其自己的线程中执行: 当执行到达该行时,将引发异常: 有谁知道如何锁定对象或函数以防止并发?我试图添加一个Lock对象: 和线 在功能开始时,但是没有用。 问题答案: 为了在一个对象上调用wait(),您必须在该对象上持有同步锁(尽管该锁实际上是在线程等待时释放的): 我必须承认,在这种情况下, 为什么 您要这样做让我感到困惑…