在Postgres 的 JDBC 驱动程序中,PGSimpleDataSource线程安全吗?
也就是说,如果我使用该类的缓存单例实例,我可以将其传递给多个线程吗?getConnection每个线程可能在同一时刻调用。该文档没有提及线程安全。
我试图避免 (a) 对 a 进行多线程调用Connection和 (b) 使用连接池,如doc 中所述。我想要Connection每个 servlet 线程都有一个单独的线程。
请考虑这段代码:
public class BusinessClass
{
static BusinessClass myClass { get; set; }
Repository repo;
public BusinessClass()
{
if (repo == null)
repo = new RepositoryClass();
}
public static BusinessClass Instance
{
get
{
if (myClass == null)
myClass = new BusinessClass();
return myClass ;
}
}
public void Update(Entity Item)
{
repo.Update(Item);
}
}
Run Code Online (Sandbox Code Playgroud)
我想BL在我的网页中使用它,如下所示:
BusinessClass.Instance.Update(Item);
Run Code Online (Sandbox Code Playgroud)
我的问题是:这段代码对于线程安全有问题吗?方法上两个人可以同时走到一起吗Update?
谢谢
我有一些使用本地范围、程序生命周期对象的 C++ 代码,例如
void testFunction(int arg) {
static Tested tested(0);
tested.use(arg);
}
Run Code Online (Sandbox Code Playgroud)
它与旧版本的 GCC 构建得很好。使用 GCC 8.2.0,我在链接时收到令人费解的警告:
警告:使用旧版兼容的 __sync_synchronize。不适合多线程应用
它指向定义测试的行,并且确实存在对编译器生成的 __sync_synchronize() 的调用。我想它是为了确保没有两个线程可以同时运行初始化代码,并使延迟初始化产生与加载时初始化相同的结果。
Tested 类的此实现重现了问题:
class Tested {
int sum;
public:
Tested(int init) : sum(init) {}
void use(int arg) {
sum += arg;
}
int current() const {
return sum;
}
};
Run Code Online (Sandbox Code Playgroud)
该代码预计在单线程嵌入式平台上运行。
我是否正确地认为该警告与我无关?
我可以做什么(除了停止使用静态对象)来消除警告消息?
我有一个下面的代码有时会出现分段错误?
vector<int> myvector;
void function1()
{
for(int i = 0;i<10;i++)
{
cout<<"writer thread:"<<i<<endl;
myvector.push_back(i);
}
}
void function2()
{
for(int i = 0;i<10;i++)
{
cout<<"reader thread:";
cout<<myvector[i]<<endl;
}
}
int main()
{
thread t1(function1);
thread t2(function2);
t1.join();
t2.join();
}
Run Code Online (Sandbox Code Playgroud)
我对一般容器和特别是向量的线程安全规则/保证有点困惑。我在一次采访中被问到这个问题,但没有说清楚为什么在线程中写入和在其他线程中写入不是线程安全操作。
在下面的向量 Push_back 链接中,我在数据争用部分看到“否则,不会访问任何现有元素,并且同时访问或修改它们是安全的”。该声明如何证明向量写入操作不是线程安全的?
据我所知,可以调用线程安全函数而无需互斥或信号量。他们不能吗?
例如,strcpy()orstrdup()是一种线程安全函数。
但是当我阅读手册页时,我看到了以下内容,但不明白这句话以及粗体示例。
MT 安全并不意味着函数是原子的,也不意味着它使用 POSIX 向用户公开的任何内存同步机制。甚至有可能按顺序调用 MT-Safe 函数不会产生 MT-Safe 组合。 例如,让一个线程依次调用两个 MT 安全函数并不能保证与这两个函数的组合的原子执行等效的行为,因为其他线程中的并发调用可能会以破坏性方式进行干扰。
线程函数中以下用法是否错误?如果是的话,错误的地方是什么?如果不是,加粗的引述是什么意思?
char *s1 = calloc(14, 1);
char *s2 = calloc(6, 1);
char *s3 = strdup("soner");
char *s4 = strdup("stackoverflow");
strcpy(s2, s3);
strcpy(s1, s4);
s1[13] = s2[5] = 0;
mutex_lock(&mtx);
printf("%s %s", s1, s2);
fflush(stdout);
mutex_unlock(&mtx);
free(s1);
free(s2);
free(s3);
free(s4);
Run Code Online (Sandbox Code Playgroud) 这可能是一个与语言无关的问题,但实际上我对 C++ 的情况感兴趣:如何用支持 MT 编程的 C++ 版本编写多线程程序,即具有内存模型的现代 C++,如何证明是正确的?
在旧的 C++ 中,MT 程序只是根据 pthread 语义编写,并根据 pthread 规则进行验证,这在概念上很简单:正确使用原语并避免数据竞争。
现在,C++ 语言语义是根据内存模型定义的,而不是根据原始步骤的顺序执行来定义的。(该标准还提到了“抽象机器”,但我不再明白它的含义。)
如何用非顺序语义证明 C++ 程序的正确性?一个程序没有一个接一个地执行原始步骤,怎么能推理出这个程序呢?
假设我有一个类似的结构:
pub struct MyStruct {
f: Arc<dyn Fn(Vec<f64>) -> Vec<f64>>,
}
impl MyStruct {
pub fn new(f: Arc<dyn Fn(Vec<f64>) -> Vec<f64>>) -> MyStruct {
MyStruct { f }
}
pub fn start(&self) {
for _ in 0..5 {
let f = self.f.clone();
thread::spawn(move || {
let v: Vec<f64> = get_random_vector();
let v = (f)(v);
// do something with v
});
}
}
}
Run Code Online (Sandbox Code Playgroud)
我收到一个错误,指出该函数无法在线程之间安全地共享,因为该dyn Fn(Vec<f64>) -> Vec<f64>)类型未实现Sync。
我可以做一个黑客,我可以将 包装在 Wrapper 结构中,然后使用 usingArc<dyn Fn(Vec<f64>) -> Vec<f64> …
public async Task<Informations> DoSthAsync
{
var informations = new List<Informations>();
await Task.WhenAll(FirstTask(informations), SecondTask(informations));
return informations;
}
public async Task FirstTask(List<Informations> list)
{
await Task.Run( () => //do sth with list);
}
public async Task SecondTask(List<Informations> list)
{
await Task.Run( () => //do sth with list);
}
Run Code Online (Sandbox Code Playgroud)
我想问一下,当两个任务使用同一个列表时,这段代码是否会导致问题?
谢谢。
该问题出现在有关 GroovyShell 的所有问题的评论中,例如使用 GroovyShell 作为“表达式求值器/引擎”(或:如何重用 GroovyShell)。这并不奇怪,因为 API 的设计似乎根本没有涵盖这个主题。不幸的是,这一点从未被明确讨论过。
问题的紧凑形式:
静态初始化:
final GroovyShell shell = new GroovyShell();
final Script thisScript = shell.parse("sleep 1000; return input1+' '+input2");
//anotherScript = // not relevant here but my use-case pre-loads ~300 groovy scripts
Run Code Online (Sandbox Code Playgroud)
脚本运行器:
private Object runScript(Script theScript, String param1, String param2) {
theScript.setProperty("input1", param1);
theScript.setProperty("input2", param2);
Object result = theScript.run();
return result;
}
Run Code Online (Sandbox Code Playgroud)
序列化执行:
runScript(thisScript, "Hello", "World") -> Hello World
runScript(thisScript, "Guten", "Tag") -> Guten Tag
Run Code Online (Sandbox Code Playgroud)
并行执行:
runScript(thisScript, "Hello", "World") -> Guten …Run Code Online (Sandbox Code Playgroud) 我有一个复杂对象的字典,只要数据库及其源数据发生更改,就需要更新该字典。条目可能已更改、添加或删除,因此本质上我们需要重新创建/重新加载整个词典。据我所知,有几种不同的方法可以做到这一点,我想知道是否有最佳实践?(或者如果我对比较的理解是正确的)
锁定语句,逐项清除和添加
lock (myLock){
myDict.Clear();
foreach (var itemToAdd in itemsToAdd)
myDict.Add(config.key, config);
}
Run Code Online (Sandbox Code Playgroud)
逐项添加到字典中,然后删除不应该存在的内容
var tmpDict = LoadDictionary();
foreach(var key in myDict.Keys.ToList()) //check for deleted keys
if(!tmpDict.ContainsKey(key))
myDict.TryRemove(key, out _);
foreach(var pair in tmpDict) //update or add every key
myDict[pair.Key] = pair.Value;
Run Code Online (Sandbox Code Playgroud)
进行直接交换(合并将军的评论)
public ConcurrentDictionary<string, string> myDict = new ConcurrentDictionary<string, string>();;
public void UpdateDictionary(){
Interlocked.Exchange(ref myDict, LoadDictionary());
}
Run Code Online (Sandbox Code Playgroud)
据我所知,只要您从不在其他地方存储对字典的引用(因为您不会获得对引用字典的任何更新),最后一个选项就应该可以正常工作。第一个选项将停止任何访问,直到更新字典(如果担心过时的值,则更安全,并且对于较小的字典来说应该没问题),第二个选项避免锁定对象并避免丢失引用,但运行您收到更新提示后几毫秒/秒内访问旧值的风险
这是一个格式相当糟糕的问题(抱歉),但是是否有执行上述操作的最佳实践/标准?和/或上述代码片段中是否存在重大漏洞?
编辑:在我的用例中,我们有几个独立的服务正在运行,数据库将被其中一个服务更改,所以我们不能先更新字典,但有点过时也没什么大不了的。
Edit2:误解了 interlocked.exchange 的作用,但仍然改进了我的解决方案
thread-safety ×10
c# ×3
c++ ×3
java ×2
asp.net ×1
c ×1
c#-6.0 ×1
concurrency ×1
devkitpro ×1
dictionary ×1
groovyshell ×1
jdbc ×1
ld ×1
memory-model ×1
postgresql ×1
rust ×1
unix ×1
vector ×1