嵌套的原子操作是否保证是原子的?

时间:2017-10-07 03:06:05

标签: c++ multithreading c++11 atomicity

如果已经回答了这个问题,或者我错过了一些明显的东西,请道歉。

我试图了解std::atomic对原子性的保证有多深。例如,如果我们有

std::atomic<int> a(0);
a.store(1);

商店运营是原子的。但是,如果我们有嵌套的原子操作会发生什么,例如:

std::atomic<int> a(0);
std::atomic<int> b(1);
a.store(++b);

我的理解是++b是原子的,store()也是。{1}}。我是否正确地认为这可以保证2原子地存储在a中?

更重要的是,如果ab在线程T1T2之间共享,是否保证两个线程执行的a.store(++b);将会在每个线程中以原子方式将b的递增值(由各个线程看到)存储到a中?换句话说,可以将T2&#34;对接在&#34;并且在 b已经增加一次之后再次增加{em} {em> 之前将结果存储到T1中{{1} }}?

3 个答案:

答案 0 :(得分:2)

增量是原子的,存储是原子的,但两个操作不是。第一个线程有可能递增b,被挂起,然后另一个线程递增b并将该值存储在a中,然后第一个线程恢复并存储它(现在是陈旧的) b的值a

答案 1 :(得分:1)

原子性不构成。

假设没有其他人写过@Embeddable public class SnippetDetailPrimaryEntity implements Serializable { @ManyToOne @JoinColumn(name = "snpt_id") private SnippetEntity snippetEntity; @Column(name = "lang_cd") private String language; } @Entity @Table(name = "snippet_detail") public class SnippetDetailEntity implements Serializable { @EmbeddedId private SnippetDetailPrimaryEntity snippetDetailPrimaryEntity; @Column(name = "snpt_type_cd") private String snippetType; @Column(name = "snpt_desc") private String snippetDescription; @Column(name = "snpt_txt") private String snippetText; @Temporal(TemporalType.TIMESTAMP) @Column(name = "cretn_ts") private Date creationTimeStamp; @Column(name = "cretn_user_id") private String creationUserId; @Temporal(TemporalType.TIMESTAMP) @Column(name = "updt_ts") private Date updatedTimeStamp; @Column(name = "updt_user_id") private String updatedUserId; } a并且另一个线程尝试在它们存在后读取它们,并且它们读取b然后b,则可能的读取正是:

a

如果他们阅读{b,a} {1,0} {2,0} {2,2} 然后a

b

在这种情况下与{a,b} {0,1} {0,2} {2,2} 相同,然后是b

答案 2 :(得分:1)

> git clone https://github.com/vim/vim.git 
> cd src
> mingw32-make -f Make_ming.mak gvim.exe 
> gvim.exe -c "%s,Sun,SUNDAY,gicp#" testfile.txt
> git diff ex_cmds.c

--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -5095,6 +5095,7 @@ do_sub(exarg_T *eap)
 #endif
                ); ++lnum)
     {
+       int show_change=FALSE;
        nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
                                                       (colnr_T)0, NULL, NULL);
        if (nmatch)
@@ -5432,8 +5433,10 @@ do_sub(exarg_T *eap)
                        }
                        if (typed == 'n')
                            break;
-                       if (typed == 'y')
+                       if (typed == 'y') {
+                           show_change=TRUE;
                            break;
+                       }
                        if (typed == 'l')
                        {
                            /* last: replace and then stop */
@@ -5779,6 +5782,11 @@ skip:
                line_breakcheck();
            }

+           if (show_change) {
+               print_line(curwin->w_cursor.lnum, subflags.do_number, subflags.do_list);
+               do_sleep(10);
+               (void) plain_vgetc(); // wait for keypress
+           }
+  

相当于

a.store(++b);