C# 两个线程同时访问一个字段

namespacethreadTEST{classProgram{staticvoidMain(string[]args){ThreadTesttt=newThreadT... namespace threadTEST
{
class Program
{

static void Main(string[] args)
{
ThreadTest tt = new ThreadTest(); // 创建一个实例
new Thread(tt.Go).Start();
tt.Go();
Console.ReadKey();

}

class ThreadTest
{
public bool done;
public void Go()
{
if (!done) { done = true; Console.WriteLine("Done"); }
}
}
}
}
为什么输出只有一个done,我的理解是 当 tt.Go();主线程执行值,新的线程才start?,done默认是false,按理说不可能每次主线程改变了done后,新线程才进来啊,这是其一,其二,done要是static 结果为什么是一个done或者两个done呢 求解释!
展开
 我来答
freeeeeewind
2014-05-09 · TA获得超过1万个赞
知道大有可为答主
回答量:3227
采纳率:94%
帮助的人:1363万
展开全部

1)在程序中加入线程信息以便观察究竟哪个线程改变了done字段

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程Id:{0}", Thread.CurrentThread.ManagedThreadId);
            ThreadTest tt = new ThreadTest();
            new Thread(tt.Go).Start();
            tt.Go();
            Console.ReadKey();
        }
    }
    class ThreadTest
    {
        public static bool done;
        public void Go()
        {
            int tId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("执行Go的线程为:{0}", tId);
            if (!done) 
            {
                Console.WriteLine("修改done的线程为:{0}",tId);
                done = true; 
                Console.WriteLine("Done"); 
            }
        }
    }

2)上面的程序存在多线程对done字段发送"争用"的可能,因此会有1个或2个done输出。当输入2个done时,表示发生了争用。争用与done是否为static无关

追问
谢谢 好像明白一点了,基本是主线程先执行,然后执行一点在换新线程分片的走,还有我感觉bool这里用public和static 没什么区别啊?难道如果是public,也就是每次程序进来的时候默认都是false,只不过另一个执行到done为true了新线程才判断if?static就是保存了旧值 望解释!
追答

1)public static bool done与public bool done唯一的区别在于:前者是类字段;后者是实例字段。类字段的特征是:字段不需要实例化就存在,例如在你的程序里,你可以这样写:

class ThreadTest {
   public static bool done;
   ……
}
……
//不需要实例化ThreadTest类就可以使用done字段
ThreadTest.done = true;

2)static done 不会保存“旧的值”。

之所以让你举得似乎“static done 保存了旧的值”,原因仍然是多线程“争用”!例如,可能出现以下“争用”:

主线程执行Go(),在执行done=true之前,主线程被调度出执行序列(停止执行)。

此时,第二线程执行Go(),而且顺利的执行完if语句块(因为done=false),输出了一个"done";

然后,主线程又被调度进执行序列,开始执行done=true和Console.WriteLine("Done")。这样,你就会看到输出2个"done"

什么时候线程被调度停止,什么时候又被调度开始执行,完全由操作系统决定,程序是无法干预的。

落月Prc
2014-05-09 · TA获得超过2789个赞
知道大有可为答主
回答量:2011
采纳率:100%
帮助的人:2443万
展开全部
第一个问题,
new Thread(tt.Go).Start(); //GO1
tt.Go(); //GO2
上面两个GO1和GO2,哪个先执行,是不一定的,都有可能(C#多线程的特性决定的)。
不管哪一个先执行,tt这个对象的done都会被修改成true了,第二个就不会输出了。
第二个问题,如果done是static,那么还是只输出一个,因为第一个已经将done修改为true了。
追问
按照你的说法 public 和static在这里是等效??
追答
不能说是等效。
第一种里面,两个GO所访问的done,是同一个对象的一个变量。
第二种里面,两个GO所访问的done,是同一个静态变量。
重点在于,他们访问的是“同一个”。
本回答被网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
仆榆信庄静
2019-09-10 · TA获得超过1146个赞
知道小有建树答主
回答量:2015
采纳率:100%
帮助的人:9.4万
展开全部
如果只是访问,不会有死锁。如果需要用锁,写两个方法,一个专门设置其值,一个专门取其值,方法内部都lock同一个对象,这样就不会出现死锁问题了。另外....netmf里有没有lock我不太清楚了,反正思路是这样。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(1)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式