我正在阅读Java Concurrency in Practice,并且与线程限制概念相混淆.这本书说的
当一个对象局限于一个线程时,即使受限制的对象本身不是这样,这种用法也是自动线程安全的
因此,当一个对象局限于一个线程时,没有其他线程可以访问它吗?是否意味着被限制在线程中?如何将对象限制在线程中?
编辑: 但是,如果我仍然想与另一个线程共享该对象怎么办?假设在线程A完成对象O之后,线程B想要访问O.在这种情况下,在完成A之后,O仍然可以被限制在B吗?
使用局部变量是一个肯定的例子,但这只是意味着你不与其他线程共享你的对象(AT ALL).在JDBC连接池的情况下,一旦线程完成该连接,它就不会将一个连接从一个线程传递到另一个线程(因为我从未使用过JDBC,所以完全无关).
java concurrency multithreading thread-safety thread-confinement
我有一个"简单"的4类示例,可以在多台计算机上可靠地显示java同步的意外行为.正如你可以在下面看到的那样,给定java sychronized关键字的契约,Broke Synchronization永远不应该从类TestBuffer中打印出来.
以下是将重现问题的4个类(至少对我而言).我对如何修复这个破碎的例子并不感兴趣,而是为什么它首先打破了.
这是我运行时获得的输出:
java -cp . SyncTest
Before Adding
Creating a TestBuffer
Before Remove
Broke Synchronization
1365192
Broke Synchronization
1365193
Broke Synchronization
1365194
Broke Synchronization
1365195
Broke Synchronization
1365196
Done
Run Code Online (Sandbox Code Playgroud)
更新:@Gray有一个最简单的例子,到目前为止.他的例子可以在这里找到:奇怪的JRC比赛条件
基于我从其他人那里获得的反馈,看起来问题可能发生在Windows 64和OSX上的Java 64位1.6.0_20-1.6.0_31(不确定更新的1.6.0)上.没有人能够在Java 7上重现该问题.它还可能需要多核机器来重现该问题.
原始问题:
我有一个类提供以下方法:
我把问题简化为下面的两个函数,这两个函数都在同一个对象中,它们都是synchronized.除非我弄错了,否则永远不应该打印"Broke Synchronization",因为在输入insideGetBuffer之前应始终将其设置为false remove.但是,在我的应用程序中,当我有1个线程调用重复删除而另一个重复调用getBuffer时,它正在打印"Broke Synchronization".症状是我得到了ConcurrentModificationException.
我自己写了一个多线程随机生成器
public static class MyRandGen
{
private static Random GlobalRandom = new Random();
[ThreadStatic]
private static Random ThreadRandom = new Random(SeedInitializer());
private static int SeedInitializer()
{
lock (GlobalRandom) return GlobalRandom.Next();
}
public static int Next()
{
return ThreadRandom.Next();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,它在抛出Next()时抛出了NullReferenceException,我不明白.这种初始化ThreadStatic字段是否被禁止?
我知道我可以检查每次都是否已初始化该字段,但这不是我正在寻找的解决方案.
实体框架生成的上下文对象不是线程安全的.
如果我使用两个独立的实体上下文,每个线程一个(并SaveChanges()在每个上调用),这会是线程安全的吗?
// this method is called from several threads concurrently
public void IncrementProperty()
{
var context = new MyEntities();
context.SomeObject.SomeIntProperty++;
context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
我相信实体框架上下文实现了某种"计数器"变量,它跟踪上下文中的当前值是否是新鲜的.
我正在C#中构建一个多线程缓存,它将包含一个Car对象列表:
public static IList<Car> Cars {get; private set;}
Run Code Online (Sandbox Code Playgroud)
我想知道在没有锁定的情况下更改线程中的引用是否安全?
例如
private static void Loop()
{
while (true)
{
Cars = GetFreshListFromServer();
Thread.Sleep(SomeInterval);
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,它归结为是否为汽车分配新的参考是原子的还是不是我想的.
如果不是,我显然必须为我的汽车使用私人领域,并锁定获取和设置.
在看了Herb Sutter的演讲" 你不知道const和mutable"之后,我想知道我是否应该总是将互斥量定义为可变的?如果是的话,我想同样适用于任何同步容器(例如tbb::concurrent_queue)?
一些背景:在他的演讲中,他说const == mutable == thread-safe,并且std::mutex每个定义都是线程安全的.
关于这个话题也有相关的问题,const在C++ 11中是否意味着线程安全.
编辑:
在这里,我发现了一个相关的问题(可能是重复的).不过,它在C++ 11之前被问过.也许这会产生影响.
我主要关心的是布尔标志......没有任何同步就可以安全地使用它吗?我在几个地方读到它是原子的(包括文档).
class MyTask
{
private ManualResetEvent startSignal;
private CountDownLatch latch;
private bool running;
MyTask(CountDownLatch latch)
{
running = false;
this.latch = latch;
startSignal = new ManualResetEvent(false);
}
// A method which runs in a thread
public void Run()
{
startSignal.WaitOne();
while(running)
{
startSignal.WaitOne();
//... some code
}
latch.Signal();
}
public void Stop()
{
running = false;
startSignal.Set();
}
public void Start()
{
running = true;
startSignal.Set();
}
public void Pause()
{
startSignal.Reset();
}
public void Resume()
{
startSignal.Set();
}
} …Run Code Online (Sandbox Code Playgroud) 我有多个线程同时调用push_back()共享对象std::vector.是std::vector线程安全的?或者我是否需要自己实现该机制以使其线程安全?
我想避免做额外的"锁定和释放"工作,因为我是图书馆用户而不是图书馆设计师.我希望寻找现有的矢量线程安全解决方案.怎么样boost::vector,这是从1.48.0以后新推出的.它是线程安全的吗?
性能如何std::mutex相比CRITICAL_SECTION?它是否相提并论?
我需要轻量级同步对象(不需要是一个进程间对象)是否有任何接近CRITICAL_SECTION其他的STL类std::mutex?
这个警告导致一个严重的问题,因为我真的无法使用Xcode 9 beta 2在主线程之外调用委托.奇怪的是,当我使用Xcode 8.3.3时,这是有效的.
另外我认为只从主线程调用委托只是好习惯,不是吗?那么为什么这会导致应用程序崩溃呢?
thread-safety ×10
c# ×4
c++ ×3
concurrency ×2
java ×2
stl ×2
boost ×1
c++11 ×1
cocoa-touch ×1
const ×1
datacontext ×1
ios ×1
mutable ×1
mutex ×1
random ×1
std ×1
threadstatic ×1