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

是否有我可以使用的不可重入读写库?

秦建元
2023-03-14

我需要一个不可重入的读写锁,因为锁可能由获取它的线程以外的线程释放。(我意识到这一点时,我开始间歇性地获取非法监视器状态异常。)

我不确定不可重入是否是正确的术语。ReentrantLock允许当前持有锁的线程再次获取它。我不想要这种行为,因此我称之为“不可重入”。

上下文是我有一个使用线程池的套接字服务器。每个连接没有一个线程。请求可能由不同的线程处理。客户端连接可能需要在一个请求中锁定,在另一个请求中解锁。由于请求可能由不同的线程处理,因此我需要能够在不同的线程中锁定和解锁。

为了回答这个问题,假设我需要继续使用这个配置,并且我确实需要在不同的请求中锁定和解锁,因此可能需要不同的线程。

这是一个读写锁,因为我需要允许多个“读者”或一个独家“作家”。

这看起来像是可以使用AbstractQueuedSynChronzer编写的,但是我担心如果我自己编写,我会犯一些微妙的错误。我可以找到各种使用AbstractQueuedSynChronzer的例子,但不是ReadWriteLock。

我可以使用OpenJDK ReentrantReadWriteLock源代码并尝试删除可重入部分,但我担心我不会完全正确。

我在番石榴和阿帕奇公地找过了,但没有找到任何合适的。Apache Commons有RWLockManager,它可能会做我需要的,但我不确定,它似乎比我需要的更复杂。

共有3个答案

羊浩广
2023-03-14

不完全确定您需要什么,特别是为什么它应该是一个读写锁,但如果您有需要由多个线程处理的任务,并且您不希望它被并发处理/访问,我实际上会使用ConcurrentMap(等等)。

您可以从映射中删除任务,或者用特殊的“锁定对象”替换它,以指示它已锁定。您可以将具有更新状态的任务返回到映射以让另一个线程接管,或者您也可以将任务直接传递给下一个线程,让它将任务返回到映射。

漆雕博
2023-03-14

我知道你已经接受了另一个答案。但我仍然认为你会给自己制造一场噩梦。最终,客户将无法返回并发布这些许可证,您将开始纳闷为什么“作者”从不写作。

如果我这样做,我会这样做:

Client issues a request to start a transaction
The initial request creates a task (Runnable/Callable) and places it in an Executor for execution
The initial request also registers that task in a Map by transaction id

Client issues the second request to close the transaction
The close request finds the task by transaction id in a map
The close request calls a method on the task to indicate that it should close (probably a signal on a Condition or if data needs to be passed, placing an object in a BlockingQueue)

现在,事务任务的代码如下:

public void run() {
    readWriteLock.readLock().lock();
    try {
        //do stuff for initializing this transaction
        if (condition.await(someDurationAsLong, someTimeUnit)( {
            //do the rest of the transaction stuff
        } else {
            //do some other stuff to back out the transaction
        }
    } finally {
        readWriteLock.readLock.unlock();
    }
}
翟功
2023-03-14

信号量允许不同的线程执行许可的获取和释放。独占写入相当于拥有所有许可证,因为线程会等待所有许可证都被释放,其他线程无法获得额外的许可证。

final int PERMITS = Integer.MAX_VALUE;
Semaphore semaphore = new Semaphore(PERMITS);

// read
semaphore.acquire(1);
try { ... }
finally {
  semaphore.release(1);
}

// write
semaphore.acquire(PERMITS);
try { ... }
finally {
  semaphore.release(PERMITS);
}
 类似资料:
  • 是否可以同时从套接字读取和写入?我有一个连续读取套接字的线程。由于只有一个线程从套接字读取,因此读取操作是线程安全的。现在我有很多线程(比如 100 个)写入套接字。因此,很明显,我必须通过做这样的事情来使写入操作线程安全, 现在我有一个线程不断调用readMessage()函数(在while循环中)。据我所知,如果套接字上没有要读取的消息,语句< code > inputstream . rea

  • 这不是一个浏览器。 我打算为我的机器人做一个“黑名单”数组,这将阻止用户运行命令。然而,我似乎只能在实际的bot文件上这样做,因为我还没有找到一种方法来做一个外部方法。 这就是我正在使用的:

  • 问题内容: 这是场景: ThreadA将要从某些套接字读取,并将数据写入“ MyFile.txt” ThreadB将读取“ MyFile”,到达末尾时,它将循环播放,直到MyFile中有新数据可用为止(因为我不想重新打开“ MyFile.txt”,并且浪费时间,所以我到达了从我所在的位置..)。 可以做这样的事情吗? 如果没有,还有其他方法可以做这种事情吗? 问题答案: 您提到的问题是著名的生产者

  • 问题内容: 我想使用JavaScript将数据写入现有文件。我不想在控制台上打印它。我想实际将数据写入。我读了许多已回答的问题,但是他们在控制台上打印的每个位置。在某些地方,他们给出了代码,但是没有用。因此,请任何人帮助我如何实际将数据写入File。 我引用了代码,但是它不起作用:给出错误: 未捕获的TypeError:非法构造函数 在铬和 SecurityError:操作不安全。 在Mozill

  • 问题内容: 该ElasticSearch文件上写着: 别名也可以映射到多个索引,并且在指定别名时,别名将自动扩展为别名索引。 但是,当我尝试为2个索引添加别名并向两个索引写入时,似乎都没有随文档更新。如果删除其中一个别名,它将正确地写入仍然存在的别名。 具有多个写别名失败: 结果: 使用单个别名: 结果: Elasticsearch是否支持写入多个索引?如果别名指向多个索引,是否为只读? 问题答案

  • 问题内容: 我是一名中级新手,擅长于AJAX。在阅读JavaScript时,我感到奇怪的是,我一直在借鉴的大多数示例都使用PHP进行了这种操作。我知道你们中许多人可能会争辩说“我做错了”或“ JavaScript是一种客户端语言”等问题,但问题仍然存在。。。您可以仅使用JavaScript编写文件吗? 问题答案: 您可以使用 Google Gears之 类的东西来生成JS应用程序,这些应用程序可以