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

Cassandra BoundStatement 的线程安全

韩寂离
2023-03-14

本文档指导如何使用Cassandra准备语句和绑定语句。

上面写着:

您应该只准备一次,并在应用程序中缓存准备好的声明(它是线程安全的)。...绑定状态不是线程安全的。您可以使用不同的参数多次重用一个实例,但只能从单个线程重用,并且只有在使用同步调用时:

BoundStatement bound = ps1.bind();

// This is safe:
bound.setString("sku", "324378");
session.execute(bound);

bound.setString("sku", "324379");
session.execute(bound);

// This is NOT SAFE. executeAsync runs concurrently with your code, so the first execution might actually read the
// values after the second setString call, and you would insert 324381 twice:
bound.setString("sku", "324380");
session.executeAsync(bound);

bound.setString("sku", "324381");
session.executeAsync(bound);

很明显,上面的代码不是线程安全的,但如果我们这样更改代码:

BoundStatement bound1 = ps1.bind();
BoundStatement bound2 = ps1.bind();

bound1.setString("sku", "324380");
session.executeAsync(bound1);

bound2.setString("sku", "324381");
session.executeAsync(bound2);

那就是:对多个线程使用通用的准备语句,每个线程都使用自己的边界语句。

1)这个线安全吗?

2)对于预处理语句的并行执行,这是推荐的方式吗?或者说,BoundStatements创建/消耗大量内存的成本高/速度慢,等等,是保持其数量较少的原因吗?

共有1个答案

米楚青
2023-03-14

简短的回答是,如果您正在考虑多次使用同一PreparedStatement对象,但每次使用不同的BoundStatement对象绑定时使用不同的参数,那么它是线程安全的,因为 是线程安全,因此您可以在多个线程中重新使用它,而 不是线程安全的每次都有不同的对象。

为了清楚起见 - 因此,您的线程 1 将使用 ps1 = session.prepare(“插入到产品(sku、描述)值 (?, ?)”) 中创建您的 prepare 语句,所有其他线程都将使用此 ps1 对象来创建自己的 BoundStatement 对象,因为每个线程都有自己的要传递的值,例如:

线程 1 将绑定并执行为(请注意,使用相同的 ps1 对象):

BoundStatement bound = ps1.bind().setString("sku", "001").setString("description", "LCD screen"); 
session.execute(bound);

线程 2 将绑定并执行为(请注意,使用相同的 ps1 对象):

BoundStatement bound = ps1.bind().setString("sku", "002").setString("description", "TFT screen"); 
session.execute(bound);

线程3将绑定并执行为(请注意,使用相同的<code>ps1</code>对象):

BoundStatement bound = ps1.bind().setString("sku", "003").setString("description", "LED screen"); 
session.execute(bound);

简而言之:创建<code>PreparedStatement</code>对象时会产生很大的性能成本,因为它需要往返于DB服务器(见下图),因此您可以重用它,并且它是线程安全的,而您每次创建一个单独的<code<BoundStatement</code>对象,因为它不是线程安全的并且它不是一个很重的创建对象,并且不需要往返于数据库服务器。

 类似资料:
  • 我找到了关于线程安全的代码,但它没有来自给出示例的人的任何解释。我想知道为什么如果我不在“count”之前设置“synchronized”变量,那么count值将是非原子的(总是=200是期望的结果)。谢谢

  • 在我的应用程序中,我使用多个线程来处理客户端连接。 我在调试时发现了一个非常奇怪的行为——我有一个SelectionKey,通过调用(使用调试器)它的interestTops()方法,返回值是1(READ),但当我将数据发送到与该键对应的套接字时,选择器不会被唤醒。。 如果使用调试器,我将特定选择键更改为1(即使是1),选择器会突然对该更改做出反应。 在给定的时间内,我只有一个线程处理一个连接,但

  • 我看到了不同的PHP二进制文件,比如非线程或线程安全? 这是什么意思? 这些软件包之间有什么区别?

  • 问题内容: 我知道Java中的双重锁定已损坏,因此使Java中的Singletons线程安全的最佳方法是什么?我想到的第一件事是: 这样行吗?如果是这样,那是否是最好的方法(我想这取决于具体情况,因此说明何时使用特定技术是最好的方法) 问题答案: Josh Bloch建议使用单元素类型实现单例(请参阅 有效的Java 2nd Edition,第3项:使用私有构造函数或枚举类型强制单例属性 )。 有

  • 问题内容: 经过一番认真的搜索后,我发现RandomAccessFile- class不是线程安全的。现在,我可以使用一个信号量来锁定所有读取和写入,但是我认为这样做的效果不是很好。从理论上讲,一次可以进行多次读取和一次写入。如何用Java做到这一点?有可能吗? 谢谢! 问题答案: 文件的部分锁定是一项复杂的业务,许多操作系统都避免这样做。但是,如果您坚持要这样做,一种方法是设计自己的锁定机制对象

  • 我们知道在 Go 语言里面 map 是非线程安全的,详细的 atomic_maps。但是我们在平常的业务中经常需要用到线程安全的 map,特别是在 goroutine 的情况下,所以 beego 内置了一个简单的线程安全的 map: bm := NewBeeMap() if !bm.Set("astaxie", 1) { t.Error("set Error") } if !bm.Chec