我有一个类的实例(我们称之为 A),它为一些线程提供服务,该实例仅通过 UdpClient 类发送 UDP 数据包。它在其构造函数中初始化 UdpClient,仅用于发送数据包。
它看起来像:
public class A{
private UdpClient m_Client;
public class A(string host, int port){
m_Client = new UdpClient(host, port);
}
public void Send(string dataToSend){
var data= encoding.GetBytes(dataToSend);
client.BeginSend(data, data.Length, null, null);
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
我知道 UdpClient 不是线程安全的(根据 MSDN 文档),不使用锁定机制支持多线程的最佳方法是什么?
在每次发送时创建 UdpClient 的新实例?(只需使用一些本地 UdpClient var)。表现?
对 UdpClient 使用 ThreadLocal?但是在这种情况下如何处置 UdpClient 呢?
还有其他解决方案吗?
我注意到一些有趣的事情。
有人告诉我(从我读到的内容来看),将请求范围变量保存在 a 中是安全的ThreadLocal(假设您无权访问请求对象并且无法使用请求属性)
嗯,它似乎有效(至少当我签入 tomcat 时)。例如,即使池中有 10 个线程,线程局部变量似乎也只在单个请求的范围内有效。我的意思是,即使我看到相同的线程名称(假设池中有 10 个线程,所以在 10 个请求之后我应该看到一些重复)每个请求都会“神奇地”重置该线程的所有线程局部变量。
真的吗?
每次请求线程返回到池中时,它都会清除所有线程本地变量吗?如何?
(这是 SLES 上的 Java 8 和 Tomcat 8,FWIW。)
当我在多个线程中使用单个实例时,在初始播种后我需要多么担心性能问题SecureRandom(特别是提供者SHA1PRNG的算法SUN) ?是线程安全的,因此这意味着一定程度的潜在争用?SecureRandomSecureRandom
我在 Java 8 Javadocs 中没有看到任何讨论这一点的内容,SecureRandom尽管我看到 Javadocs确实特别警告了跨线程Random使用单个实例时的争用和性能下降。Random
我们正在考虑使用单个实例,因为从我们看来,在我们的方法(用于IV 生成)中SecureRandom获取新实例的成本太高,因为如果您在使用新实例之前使用几次,那么播种开销就会杀死您。完成了。SecureRandomencrypt()SecureRandomSecureRandom
或者,我们正在考虑让ThreadLocal<SecureRandom>包含该encrypt()方法的类有一个静态成员,以便每个SecureRandom线程使用一个静态成员。我们故意不调用,因为如果我们走这条路线,我们实际上希望实例尽可能长时间地“存活”在 tomcat 线程中(以最小化创建ThreadLocal.remove()新实例的次数)。SecureRandom
从这里阅读有关ThreadLocal内存泄漏的内容后,我对这种方法有些担忧。然而,我们实际上从不重新部署 web 应用程序。它用在嵌入式系统中,当 webapp 升级时(这是整个系统升级的一部分,一年只发生几次)Tomcat 完全关闭,新的 war 文件被删除,Tomcat 重新启动。这似乎会让与 Web 应用程序相关的ThreadLocal泄漏变得毫无意义。
那么,是否有任何关于“有争议”程度的良好数据SecureRandom,以及对于如何SecureRandom在重度多线程环境中最正确地使用达成共识?
我目前正在构建一个系统,其中有多个线程正在运行,一个线程可以将工作排队到另一个线程并等待完成。我使用互斥体和条件变量进行同步。为了避免为每个操作创建新的互斥体和 cv,我想对其进行优化,并尝试为每个正在等待的线程使用 thread_local 互斥体/cv 对。然而,这出乎意料地不起作用,我很有趣为什么。
基本上我的代码将工作排队到另一个线程并等待它,如下所示:
/* thread_local */ std::mutex mtx;
/* thread_local */ std::condition_variable cv;
bool done = false;
io_service.post([&]() {
// Execute the handler in context of the io thread
functionWhichNeedsToBeCalledInOtherThread();
// Signal completion to unblock the waiter
{
std::lock_guard<std::mutex> lock(mtx);
done = true;
}
cv.notify_one();
});
// Wait until queued work has been executed in io thread
{
std::unique_lock<std::mutex> lk(mtx);
while (!done) cv.wait(lk);
}
Run Code Online (Sandbox Code Playgroud)
如果同步对象不是,则此方法可以正常工作thread_local。当我添加thread_local等待线程时,它会永远等待,这表明条件变量永远不会发出信号。我现在有一种感觉,尽管通过引用捕获对象,但另一个线程的 thread_local 对象在 lambda 内部使用。mtx我什至可以通过检查lambda 内部和外部的地址来确认捕获没有执行正确的操作-> 它们不匹配。 …
我有以下情况:在标头“test.hpp”中我定义:
class ObjectA {
public:
ObjectA();
~ObjectA();
static ObjectA & get_A();
};
class ObjectB {
public:
~ObjectB();
static ObjectB & get_B();
void do_cleanup();
};
Run Code Online (Sandbox Code Playgroud)
在单独的编译单元中,我实现了 ObjectB:
#include "test.hpp"
#include <iostream>
ObjectB::~ObjectB() {
std::cout<<"ObjectB dtor"<<std::endl;
}
ObjectB & ObjectB::get_B() {
thread_local ObjectB b_instance;
return b_instance;
}
void ObjectB::do_cleanup() {
std::cout<<"Clearing up B garbage..."<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
对象A:
#include "test.hpp"
#include <iostream>
ObjectA::ObjectA() {
ObjectB::get_B(); <--dummy call to initialize thread_local ObjectB;
}
ObjectA::~ObjectA() {
std::cout<<"ObjectA dtor"<<std::endl;
ObjectB::get_B().do_cleanup(); // <-- is this undefined behaviour??
} …Run Code Online (Sandbox Code Playgroud) 我在文件 tracker.hpp 中有一个变量:
namespace TRIALS
{
static thread_local int a = -1;
}
Run Code Online (Sandbox Code Playgroud)
我在 ema.hpp/ema.cpp 中的文件中有另一个名为 EMP 的类
namespace Algo
{
class EMP
{
public:
void Sample();
};
}
Run Code Online (Sandbox Code Playgroud)
namespace Algo
{
void EMP::Sample()
{
std::cout << "model " << std::this_thread::get_id() << " " << &TRIALS::a << " " << TRIALS::a << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我的主文件
auto model = Algo::EMP();
void Simulate(const int a)
{
TRIALS::a = a;
model.Sample()
std::cout << "worker " << std::this_thread::get_id() << " " << &TRIALS::a …Run Code Online (Sandbox Code Playgroud) 而不是编写以下非线程安全的方法.
private static final Calendar calendar = Calendar.getInstance();
public void fun() {
// Going to call mutable methods in calendar.
}
Run Code Online (Sandbox Code Playgroud)
我将其更改为线程安全版本.
public void fun() {
final Calendar calendar = Calendar.getInstance();
// Going to call mutable methods in calendar.
}
Run Code Online (Sandbox Code Playgroud)
即使对于同一个线程,我也不是每次创建一个新实例,而是通过执行改进
public void fun() {
final Calendar calendar = getCalendar();
// Going to call mutable methods in calendar.
}
/**
* Returns thread safe calendar.
* @return thread safe calendar
*/
public Calendar getCalendar() {
return calendar.get();
}
private static …Run Code Online (Sandbox Code Playgroud) 外行人说,当有人说某个对象是Java中的线程单一单例时,它意味着什么?我正在参加有关Java Server Faces的讲座,每次谈到FacesContext时 - 讲师总是提醒我们这是一个线程单一的单身人士.
thread-local ×10
java ×5
c++ ×3
.net ×1
c# ×1
capture ×1
concurrency ×1
destructor ×1
encryption ×1
facescontext ×1
jsf ×1
lambda ×1
rust ×1
servlets ×1
tomcat ×1
udpclient ×1