在我读过的大多数讨论中,它表明使属性原子不能保证它是线程安全的,它只是保证返回的值不会是一个对象写入它而另一个对象的垃圾.试图同时阅读它.
我理解这不是线程安全的,因为第三个对象可能正在编写它,而访问它的对象不会被垃圾回收,但是当多个对象同时写入它时,它不能完全确定它将返回哪个值时间,它可能会得到他们的任何价值观.
因此,当我们说它不会返回垃圾时,垃圾是否意味着如果一个对象是非原子的并且一个对象试图访问它而另一个对象正在写入它,那么它可能会在写入中间得到结果,并且只能获得写入所带来的部分不完整版本的更改?这就是"垃圾"在这个意义上意味着什么,以及什么原子属性有助于防止?
我正在尝试创建一个保存对象的视图,但是如果引发一些异常,我想撤消该保存.这是我试过的:
class MyView(View):
@transation.atomic
def post(self, request, *args, **kwargs):
try:
some_object = SomeModel(...)
some_object.save()
if something:
raise exception.NotAcceptable()
# When the workflow comes into this condition, I think the previous save should be undome
# Whant am I missing?
except exception.NotAcceptable, e:
# do something
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?即使引发异常some_object仍然在DataBase中.
有人可以解释一下atomicModifyIORef有效吗?特别是:
(1)是否等待锁定,或者乐观地尝试重试(如果存在争用TVar).
(2)为什么签名atomicModifyIORef不同于签名modifyIORef?特别是,这个额外的变量是什么b?
编辑:我想我已经找到了(2)的答案,因为这b是一个要提取的值(如果不需要,这可以是空的).在单线程程序中,知道该值是微不足道的,但在多线程程序中,人们可能想知道在应用函数时先前的值是什么.我假设这就是为什么modifyIORef没有这个额外的返回值(因为这样的modifyIORef返回值的使用可能应该使用atomicModifyIORef.我仍然对(1)的答案感兴趣.
请考虑以下示例代码:
class MyClass
{
public long x;
public void DoWork()
{
switch (x)
{
case 0xFF00000000L:
// do whatever...
break;
case 0xFFL:
// do whatever...
break;
default:
//notify that something going wrong
throw new Exception();
}
}
}
Run Code Online (Sandbox Code Playgroud)
忘掉片段的无用性:我的疑问是关于switch声明的行为.
假设该x字段只能有两个值:0xFF00000000L或0xFFL.上面的开关不应该属于"默认"选项.
现在想象一个线程正在执行"x"等于0xFFL的开关,因此第一个条件将不匹配.同时,另一个线程将"x"变量修改为0xFF00000000L.我们知道64位操作不是原子操作,因此变量首先将较低的dword置零,然后将较低的dword置零(反之亦然).
如果在"x"为零时(即在新的分配期间)完成开关中的第二个条件,我们是否会陷入不希望的"默认"情况?
file_put_contents ( "file", "data", LOCK_EX )
Run Code Online (Sandbox Code Playgroud)
写作(意思是 - 获取锁定和写入)
file_get_contents ( "file", LOCK_EX )
Run Code Online (Sandbox Code Playgroud)
用于阅读(这意味着 - 获取锁定然后阅读)
它会抛出异常吗?提出错误?阻止直到获得锁定?或者至少 - 应该吗?有一天php会有这样的表现吗?
编辑:我知道可以使用重命名 - 我想知道答案...
在以下代码中:
std::atomic<int> myint; //Shared variable
//(...)
if( --myint == 0) {
//Code block B
}
Run Code Online (Sandbox Code Playgroud)
是否有可能多个线程访问名为"代码块B"的块?
请考虑溢出不会发生,'if'由多个线程同时执行,整个程序中对myint的唯一修改是if中的--myint和myint初始化为正值.
如果mem是共享内存位置,我是否需要:
XCHG EAX,mem
Run Code Online (Sandbox Code Playgroud)
要么:
LOCK XCHG EAX,mem
Run Code Online (Sandbox Code Playgroud)
原子地进行交换?
谷歌搜索这会产生是和否答案.有没有人知道这个?
我正在使用32位计算机运行,并且我能够使用以下快速命中的代码片段来确认长值可以撕裂.
static void TestTearingLong()
{
System.Threading.Thread A = new System.Threading.Thread(ThreadA);
A.Start();
System.Threading.Thread B = new System.Threading.Thread(ThreadB);
B.Start();
}
static ulong s_x;
static void ThreadA()
{
int i = 0;
while (true)
{
s_x = (i & 1) == 0 ? 0x0L : 0xaaaabbbbccccddddL;
i++;
}
}
static void ThreadB()
{
while (true)
{
ulong x = s_x;
Debug.Assert(x == 0x0L || x == 0xaaaabbbbccccddddL);
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试与双打类似的东西时,我无法得到任何撕裂.有谁知道为什么?据我从规范中可以看出,只有浮点数的赋值才是原子的.分配给双人应该有撕裂的风险.
static double s_x;
static void TestTearingDouble()
{
System.Threading.Thread A = new System.Threading.Thread(ThreadA);
A.Start(); …Run Code Online (Sandbox Code Playgroud) 由于AtomicInteger可以比int受保护的至少慢一个数量级synchronized,为什么我要使用AtomicInteger?
例如,如果我想要的是以int线程安全的方式递增值,为什么不总是使用:
synchronized(threadsafeint) {
threadsafeint++;
}
Run Code Online (Sandbox Code Playgroud)
而不是使用慢得多的AtomicInteger.incrementAndGet()?
atomicity ×10
concurrency ×3
c# ×2
c++ ×2
locking ×2
.net ×1
atomic ×1
blocking ×1
c++11 ×1
django ×1
haskell ×1
ios ×1
java ×1
objective-c ×1
performance ×1
php ×1
python ×1
transactions ×1
x86 ×1