一个java内存刷新volatile:一个好的程序设计?
这是一个与此相关的问题: 我有一个或多个不同的对象。我想更改其中的一些状态,然后我想使该状态对其他线程可见 出于性能原因,我不想让对象中的每个成员变量都是易变的。 有时我想在单线程应用程序中使用这些对象。因此,在这种情况下,波动性也会很差 所以我有以下几点:一个java内存刷新volatile:一个好的程序设计?,java,multithreading,design-patterns,concurrency,volatile,Java,Multithreading,Design Patterns,Concurrency,Volatile,这是一个与此相关的问题: 我有一个或多个不同的对象。我想更改其中的一些状态,然后我想使该状态对其他线程可见 出于性能原因,我不想让对象中的每个成员变量都是易变的。 有时我想在单线程应用程序中使用这些对象。因此,在这种情况下,波动性也会很差 所以我有以下几点: //these following mehtods change some internal variable state. These variables are not volatile or synchronized boolean
//these following mehtods change some internal variable state. These variables are not volatile or synchronized
boolean volatile memoryFlusher=false;
Thread1:
obj1->changeSomeState();
obj1->changeMoreState();
obj2->alsoSomeStateChange();
//and now i want to make that state visible to others
memoryFlusher=false; //volatile write
Thread2:
boolean tmp=memoryFlusher; // volatile read but variable is not used again
obj1->getState();
obj2->getState();
因此,到目前为止,我在一开始提到的相关问题或多或少都是一样的
现在我想问以下问题:
//these following mehtods change some internal variable state. These variables are not volatile or synchronized
boolean volatile memoryFlusher=false;
Thread1:
obj1->changeSomeState();
obj1->changeMoreState();
obj2->alsoSomeStateChange();
//and now i want to make that state visible to others
memoryFlusher=false; //volatile write
Thread2:
boolean tmp=memoryFlusher; // volatile read but variable is not used again
obj1->getState();
obj2->getState();
我的记忆过滤器没有优化?(我的另一个问题没有回答)
每个易失性写入/读取刷新所有的所有memoryState?其他(也非易失性)变量
现在真正新的问题是:
这是一个好的设计吗,我在那里做的?
因为我没有看到任何像这样的代码,我在这里发布
我应该用另一种方式编程吗?
是否有其他最佳实践来提高性能和获得可见性?
在程序设计视图中,没有这样的操作,还有其他最佳实践吗
编辑:
我更改的状态是未报告的。
所以我想用内存变量一个memoryflusher,没有锁机制。它应该将许多单个可变变量替换为一个。例如,我不需要显式的易失性内存刷新,因为我使用的是synchronized
synchronized(x)
{
...
obj1->stateChange() //if internally is used a volatile, then i have a volatile memory flush and later the synchronized-end memory-flush, i guess (is that right?)
...
}
这将是一个例子,在那里它可能是有用的
总结:
但是这是正确的吗?我认为这样使用内存刷新?您的易失性读写没有得到优化,但是我看不出这段代码有任何用处。这可能就是你在别处看不到它的原因。你没有说你期望从中得到什么,所以谁知道呢 看起来您希望确保Thread2可靠地读取Thread1所做的状态更改。好的,只有当您确定Thread2中的代码实际上在Thread1中的代码之后运行时,这才有效 你怎么知道是这样的 我建议,如果真的有任何方法可以确保Thread2代码发生在Thread1代码之后,那么已经有了一个内存屏障来确定这一事实,并使volatile变量变得不必要 我的记忆过滤器没有优化 否,写入和读取
内存刷新器
不会被优化
每个易失性写/读都会刷新所有内存的所有memoryState
是的,它会将内存同步到两个线程。但是,只有当您能够检测到从一个线程到另一个线程的更改时,它才起作用
在您的示例中,您读取了memoryFlusher
,但初始化时memoryFlusher
为false
。您如何知道线程1实际写入了它?如果线程1位于此行obj1->changeMoreState
,线程2读取memoryFlusher
,该怎么办。这两个值在这里都是false
,因此您不知道线程1是否实际完成。您不同步,因为您在订购之前还没有确定您的线程
要更正代码,应将true
写入memoryFlusher
字段,只有memoryFlusher
为true时,线程2才应继续。这有效地建立了您的顺序,但也使您的代码更加混乱
我建议用一个代替这个的。当写操作不频繁时,StampedLock可以让您快速读取 所以你的意思是,我不应该只把这个MemoryFluser用作一个MemoryFluser,更像是一个信号变量?如果(memoryFlusher==true){…}在第二个线程中?首先解释您试图使用此代码完成什么OK,但是如果Thread1再次更改状态,则我的signalvariable已经为true;在这种情况下,我必须在Thread2中再次使signalvariable无效,对吗?但是在Thread2中,我应该在哪里再次将memoryFlusher设置为false?或者我应该在这里使用布尔值以外的其他值?为什么那样更让人困惑?
为什么那样更让人困惑?
你刚才说的确切原因。也许混淆不是正确的术语,我可以更新它。这只会使代码更加难以推理,并且在您的用例中出现错误。就您的观点而言(这是一个很好的观点),如果线程1再次更改了该值怎么办?好吧,你运气不好,无法建立订单。您的代码只能执行一次。在这种情况下,StampedLock
更有意义。要安全地更新这些字段,可以多次使用StampedLock
。好的,我想了几分钟:如果对象中的状态不相关,那么我不需要知道thread1何时更改这些值。Thread2可以看到该值本身的更改。您提到的StampedLock与内部CAS操作同步的java相同,对吗?因此,在这种情况下,我得到了与锁定视图中的java synchronized相同的StampedLocks行为。但我猜存在我不想锁定状态的场景(如果状态不相关)。还是我现在有思维问题^^