Volatile Violates its main job?

前端 未结 3 1170
栀梦
栀梦 2020-12-14 17:09

According to MSDN:

The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields tha

相关标签:
3条回答
  • 2020-12-14 17:33

    Another point raised by Joseph Albahari is that process architecture can adversely impact volatile, i.e. AMD in particular can cause values to be swapped.

    Since you will probably have no idea what system type your application will run on in production its best to always avoid the volatile keyword.

    Also slightly off topic you should always avoid the ReaderWriterLock class as under heavy load on multiprocessor systems this can allow multiple write locks please see here to be taken simultaneously which will cause application hangs which will be extremely difficult to root cause

    0 讨论(0)
  • 2020-12-14 17:34

    Well you are right. It is more elaborated in Joseph Albahari threading book/article.

    The MSDN documentation states that use of the volatile keyword ensures that the most up-to-date value is present in the field at all times. This is incorrect, since as we’ve seen, a write followed by a read can be reordered.

    http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword

    Should I ( as a programmer ) need to prevent using this keyword-because of such weird behavior?

    It should be used only after knowing this weired behavior. It should not be used as a Magic keyword to retrieve latest values all the time in multithreaded environment.

    IMO, usage of volatile keyword should be avoided as probable bugs are hard to find out.

    0 讨论(0)
  • 2020-12-14 17:42

    The MSDN documentation is wrong. That is most certainly not what volatile does. The C# specification tells you exactly what volatile does and getting a "fresh read" or a "committed write" is not one of them. The specification is correct. volatile only guarantees acquire-fences on reads and release-fences on writes. These are defined as below.

    • acquire-fence: A memory barrier in which other reads and writes are not allowed to move before the fence.
    • release-fence: A memory barrier in which other reads and writes are not allowed to move after the fence.

    I will try to explain the table using my arrow notation. A ↓ arrow will mark a volatile read and a ↑ arrow will mark a volatile write. No instruction can move through the arrowhead. Think of the arrowhead as pushing everything away.

    In the following analysis I will use to variables; x and y. I will also assume that they are marked as volatile.

    Case #1

    Notice how the placement of the arrow after the read of x prevents the read of y from moving up. Also notice that the volatility of y is irrelevant in this case.

    var localx = x;
    ↓
    var localy = y;
    ↓
    

    Case #2

    Notice how the placement of the arrow after the read of x prevents the write to y from moving up. Also notice that the volatility of either of x or y, but not both, could have been omitted in this case.

    var localx = x;
    ↓
    ↑
    y = 1;
    

    Case #3

    Notice how the placement of the arrow before the write to y prevents the write to x from moving down. Notice that the volatility of x is irrelevant in this case.

    ↑
    x = 1;
    ↑
    y = 2;
    

    Case #4

    Notice that there is no barrier between the write to x and the read of y. Because of this the either the write to x can float down or the read of y can float up. Either movement is valid. This is why the instructions in the write-read case can be swapped.

    ↑
    x = 1;
    var localy = y;
    ↓
    

    Notable Mentions

    It is also important to note that:

    • x86 hardware has volatile semantics on writes.
    • Microsoft's implementation of the CLI (and suspect Mono's as well) has volatile semantics on writes.
    • The ECMA specification does not have volatile semantics on writes.
    0 讨论(0)
提交回复
热议问题