可能重复:
线程安全是什么意思?
我很困惑任何类都是Thread安全的.我理解,如果任何类是线程安全的,那么它的方法有一些特定的(同步).是对还是错?请帮助我详细说明它的含义.
这是C#的详细问题.
假设我有一个带有对象的类,并且该对象受到锁的保护:
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
return property;
}
set {
property = value;
}
}
Run Code Online (Sandbox Code Playgroud)
我想要一个轮询线程来查询该属性.我还希望线程偶尔更新该对象的属性,有时用户可以更新该属性,并且用户希望能够看到该属性.
以下代码是否会正确锁定数据?
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
lock (mLock){
return property;
}
}
set {
lock (mLock){
property = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过'正确',我的意思是,如果我想打电话
MyProperty.Field1 = 2;
Run Code Online (Sandbox Code Playgroud)
或者其他什么,我会在更新时锁定该字段?设置是由'get'函数范围内的equals运算符完成的,还是'get'函数(因此锁定)首先完成,然后设置,然后'set'被调用,从而绕过锁?
编辑:由于这显然不会做的伎俩,会是什么?我是否需要做以下事情:
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
MyObject tmp = null;
lock …
Run Code Online (Sandbox Code Playgroud) 以下是实现相当简单的线程安全日志记录类的正确方法吗?
我知道我从未明确关闭过TextWriter
,这会是一个问题吗?
当我最初使用该TextWriter.Synchronized
方法时,它似乎没有工作,直到我在静态构造函数中初始化它并使它只读它:
public static class Logger
{
static readonly TextWriter tw;
static Logger()
{
tw = TextWriter.Synchronized(File.AppendText(SPath() + "\\Log.txt"));
}
public static string SPath()
{
return ConfigManager.GetAppSetting("logPath");
}
public static void Write(string logMessage)
{
try
{
Log(logMessage, tw);
}
catch (IOException e)
{
tw.Close();
}
}
public static void Log(string logMessage, TextWriter w)
{
w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
w.WriteLine(" :");
w.WriteLine(" :{0}", logMessage);
w.WriteLine("-------------------------------");
// Update the underlying file.
w.Flush();
}
}
Run Code Online (Sandbox Code Playgroud) 查看SharedPreferences文档,它说:
"注意:目前这个类不支持跨多个进程使用.这将在以后添加."
所以它本身似乎并不是线程安全的.但是,对commit()和apply()有什么样的保证?
例如:
synchronized(uniqueIdLock){
uniqueId = sharedPreferences.getInt("UNIQUE_INCREMENTING_ID", 0);
uniqueId++;
sharedPreferences.edit().putInt("UNIQUE_INCREMENTING_ID", uniqueId).commit();
}
Run Code Online (Sandbox Code Playgroud)
是否可以保证uniqueId在这种情况下始终是唯一的?
如果没有,是否有更好的方法来跟踪持续存在的应用程序的唯一ID?
在"C#4 in a Nutshell"中,作者表明这个类有时可以写0 MemoryBarrier
但是我无法在我的Core2Duo中重现:
public class Foo
{
int _answer;
bool _complete;
public void A()
{
_answer = 123;
//Thread.MemoryBarrier(); // Barrier 1
_complete = true;
//Thread.MemoryBarrier(); // Barrier 2
}
public void B()
{
//Thread.MemoryBarrier(); // Barrier 3
if (_complete)
{
//Thread.MemoryBarrier(); // Barrier 4
Console.WriteLine(_answer);
}
}
}
private static void ThreadInverteOrdemComandos()
{
Foo obj = new Foo();
Task.Factory.StartNew(obj.A);
Task.Factory.StartNew(obj.B);
Thread.Sleep(10);
}
Run Code Online (Sandbox Code Playgroud)
这种需要对我来说似乎很疯狂.如何识别出现这种情况的所有可能情况?我认为如果处理器改变了操作顺序,它需要保证行为不会改变.
你还懒得使用障碍吗?
我读了一章,我不喜欢它.我还不清楚每个内存顺序之间的差异.这是我目前的推测,我在阅读更简单的http://en.cppreference.com/w/cpp/atomic/memory_order后理解这一点.
以下是错误的,所以不要试图从中学习
a
在另一个线程上放宽了存储.我b
用seq_cst 存储.第三个线程读取a
放松将看到变化以及b
任何其他原子变量? ).如果我错了,我想我理解但是纠正我.我找不到任何用易于阅读的英语解释它的东西.
我不知道std::atomic
变量,但是知道std::mutex
标准提供的(奇怪的权利!); 然而有一件事引起了我的注意:标准提供了两种看似相同(对我而言)的原子类型,如下所示:
它也以 - 的例子提到std::atomic_flag type
-
std :: atomic_flag是一种原子布尔类型.与std :: atomic的所有特化不同,它保证是无锁的.与std :: atomic不同,std :: atomic_flag不提供加载或存储操作.
我不明白.std::atomic bool type
不保证是无锁的吗?那它不是原子的还是什么?
那么两者之间有什么区别呢?我应该在何时使用哪种?
如何以编程方式证明StringBuilder
不是线程安全的?
我尝试过这个,但它不起作用:
public class Threadsafe {
public static void main(String[] args) throws InterruptedException {
long startdate = System.currentTimeMillis();
MyThread1 mt1 = new MyThread1();
Thread t = new Thread(mt1);
MyThread2 mt2 = new MyThread2();
Thread t0 = new Thread(mt2);
t.start();
t0.start();
t.join();
t0.join();
long enddate = System.currentTimeMillis();
long time = enddate - startdate;
System.out.println(time);
}
String str = "aamir";
StringBuilder sb = new StringBuilder(str);
public void updateme() {
sb.deleteCharAt(2);
System.out.println(sb.toString());
}
public void displayme() {
sb.append("b");
System.out.println(sb.toString());
}
} …
Run Code Online (Sandbox Code Playgroud) 在C++ 11中,你仍然需要使用std::localtime
和std::gmtime
作为间接来打印std::chrono::time_point
.这些函数在C++ 11引入的多线程环境中使用是不安全的,因为它们返回一个指向内部静态结构的指针.这尤其令人讨厌,因为C++ 11引入了方便的功能std::put_time
,由于同样的原因几乎无法使用.
为什么这么根本被打破或者我忽略了什么?
我想为实验创建一个非线程安全的代码块,这些是2个线程要调用的函数.
c = 0
def increment():
c += 1
def decrement():
c -= 1
Run Code Online (Sandbox Code Playgroud)
这段代码线程安全吗?
如果没有,我可以理解为什么它不是线程安全的,以及什么样的语句通常会导致非线程安全的操作.
如果它是线程安全的,我怎样才能使它明确地是非线程安全的?
thread-safety ×10
c# ×3
c++ ×3
c++11 ×3
atomic ×2
java ×2
.net ×1
android ×1
c++-chrono ×1
increment ×1
locking ×1
logging ×1
memory-model ×1
properties ×1
python ×1