寻找一些简单的线程池实现的示例代码(C#).
我在codeproject上找到了一个,但代码库很大,我不需要所有的功能.
无论如何,这更多是出于教育目的.
Nutshell中的C#4(强烈推荐的btw)使用以下代码来演示MemoryBarrier的概念(假设A和B在不同的线程上运行):
class Foo{
int _answer;
bool complete;
void A(){
_answer = 123;
Thread.MemoryBarrier(); // Barrier 1
_complete = true;
Thread.MemoryBarrier(); // Barrier 2
}
void B(){
Thread.MemoryBarrier(); // Barrier 3;
if(_complete){
Thread.MemoryBarrier(); // Barrier 4;
Console.WriteLine(_answer);
}
}
}
Run Code Online (Sandbox Code Playgroud)
他们提到障碍1和4阻止这个例子写0和障碍2和3提供新鲜度保证:他们确保如果B在A之后运行,读_complete将评估为真.
我不是真的得到它.我想我明白为什么壁垒1和4是必要的:我们不想在写_answer进行优化,并放置在写后_complete(屏障1),我们需要确保_answer没有被缓存(光栅4) .我也认为我理解为什么Barrier 3是必要的:如果A在写完_complete = true之后才运行,B仍然需要刷新_complete以读取正确的值.
我不明白为什么我们需要障碍2!我的一部分说这是因为可能线程2(运行B)已经运行直到(但不包括)if(_complete),因此我们需要确保_complete被刷新.
但是,我不知道这有多大帮助.是不是仍然可以在A 中将_complete设置为true但是B方法会看到_complete的缓存(错误)版本?即,如果线程2运行方法B直到第一个MemoryBarrier之后,然后线程1运行方法A直到_complete = true但没有进一步,然后线程1恢复并测试是否(_complete) - 如果不导致错误 …
c# multithreading thread-safety shared-memory memory-barriers
我正在研究VolatileRead/VolatileWrite方法的实现(使用Reflector),我对此感到困惑.
这是VolatileRead的实现:
[MethodImpl(MethodImplOptions.NoInlining)]
public static int VolatileRead(ref int address)
{
int num = address;
MemoryBarrier();
return num;
}
Run Code Online (Sandbox Code Playgroud)
在读取"地址"的值后,如何放置内存屏障?不应该是相反的吗?(在读取值之前放置,所以对于"address"的任何挂起写入都将在我们进行实际读取时完成.同样的事情发生在VolatileWrite,其中内存屏障在赋值之前放置.为什么?另外,为什么这些方法具有NoInlining属性?如果它们被内联会发生什么?
我的问题是我尝试使用Unity套接字来实现一些东西.每次,当我收到新消息时,我需要将其更新为updattext(它是Unity Text).但是,当我执行以下代码时,void update不会每次都调用.
我没有包含updatetext.GetComponent<Text>().text = "From server: "+tempMesg;
在void getInformation中的原因是这个函数在线程中,当我在getInformation()中包含它时会出现错误:
getcomponentfastpath can only be called from the main thread
我认为问题是我不知道如何在C#中运行主线程和子线程?或者可能还有其他问题...希望有人可以提供帮助..有我的代码:
using UnityEngine;
using System.Collections;
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine.UI;
public class Client : MonoBehaviour {
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
private Thread oThread;
// for UI update
public GameObject updatetext;
String tempMesg = "Waiting...";
// Use this for initialization
void Start () {
updatetext.GetComponent<Text>().text = "Waiting...";
clientSocket.Connect("10.132.198.29", 8888);
oThread = new Thread (new ThreadStart …
Run Code Online (Sandbox Code Playgroud) 我读过很多关于volatile和VoletileRead(ReadAcquireFence)的矛盾信息(msdn,SO等).
我理解那些内存访问重新排序的限制含义 - 我仍然完全混淆的是新鲜度保证 - 这对我来说非常重要.
(...)这可确保始终在字段中显示最新值.
读取volatile字段称为volatile读取.易失性读取具有"获取语义"; 也就是说,保证在指令序列之后发生的任何内存引用之前发生.
public static int VolatileRead(ref int address)
{
int ret = address;
MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
return ret;
}
Run Code Online (Sandbox Code Playgroud)
根据msdn MemoryBarrier doc内存屏障阻止重新排序.然而,这似乎对新鲜度没有任何影响 - 对吗?
如何获得新鲜度保证?标记字段volatile与使用VolatileRead和VolatileWrite语义访问它之间有区别吗?我目前正在执行我的性能关键代码,需要保证新鲜度,但读者有时会得到陈旧的价值.我想知道是否标记状态不稳定将使情况不同.
EDIT1:
我正在努力实现的目标 - 保证读者线程将尽可能获得共享变量(由多个编写者编写)的最新值 - 理想情况下不会超过上下文切换或其他可能推迟立即操作的操作的成本写国家.
如果挥发性或更高级别的构造(例如锁定)具有这种保证(是吗?)而不是它们如何实现这一点?
EDIT2:
非常简洁的问题应该是 - 如何在读取过程中尽可能保证新的价值?理想情况下没有锁定(因为不需要独占访问,并且存在高争用的可能性).
从我在这里学到的东西,我想知道这可能是解决方案(求解(?)行标有注释):
private SharedState _sharedState;
private SpinLock _spinLock = new SpinLock(false);
public void Update(SharedState newValue) …
Run Code Online (Sandbox Code Playgroud)