protobuf在Java中是线程安全的吗?

5

我有如下的协议缓冲消息定义:

message Counts {
    repeated int32 counts = 1;
}

以下是涉及IT技术的内容,需要翻译为中文:

这是一个在线程RW之间共享的构建器:

private final Counts.Builder countsBuilder;

线程R只会从countsBuilder读取,而W只会向countsBuilder写入。

共享的构建器将被读取、写入,并在某个时刻构建并通过网络发送。

据我所知,对消息的并发读取是可以接受的,但其他任何操作都必须由开发人员在更高级别上同步。所以,我实际上不能同时写入和读取共享构建器吗?

如果这不是固有的线程安全性,则考虑使用某种线程安全的Collection<Integer>,用于读取/写入,并在发送到网络之前(在某个时候)创建全新的消息。或者我错过了什么吗?

谢谢!

编辑1:我正在使用protobuf 2.4.1和java 6

编辑2:一些术语和拼写修正。


2
你会如何提议“写入共享消息”?消息是不可变的。你必须写入构建器。 - Jon Skeet
哎呀,我相信我使用了错误的术语。在发送时,我会写给构建器并转换为消息。 - Howie
2个回答

2
根据https://developers.google.com/protocol-buffers/docs/reference/cpp,在C++中它不是线程安全的。
而且在Java中也不是https://developers.google.com/protocol-buffers/docs/reference/java-generated
我最近遇到了这个问题,并找到了以下内容。下面是C++的说明:
引用: 关于线程安全的说明: 协议缓冲区库中的线程安全遵循一个简单的规则:除非有明确的注释说明,否则只要对象在所有线程中都被声明为const(或者,仅在允许声明为const的情况下使用),就可以同时从多个线程使用该对象。但是,如果一个对象以一种不允许的方式在一个线程中被访问,那么在任何其他线程中访问该对象都是不安全的。 简而言之,只读访问可以在多个线程中同时进行,但写访问只能在一个线程中进行。
Java的说明如下:
请注意,构建器(builder)不是线程安全的,因此当多个不同的线程需要修改单个构建器的内容时,应使用 Java 同步(synchronization)。

2

如果您同步读取和写入,则应该没有问题:

synchronized (countsBuilder) {
   // modify countsBuilder
}

但是请记住,在构建消息时,您还需要确保没有竞争条件;写入线程在构建消息后不允许进行任何写操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接