关于多个线程操作同一变量遇到问题,求指教

时间:2022-11-26 18:12:24
我想实现多个线程对同一个变量进行累加,当某个线程发现这个变量超过指定值比如300,就在这个线程内部结束所有的线程运行,我写的代码如下,为什么运行的时候还是有些线程没有被结束掉呢?

        private int flag = 0;
        Thread[] threads = new Thread[20];
        private object LockThis = new System.Object();

        private void button4_Click(object sender, EventArgs e)
        {            
            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(new ParameterizedThreadStart(threadMethod));
                threads[i].Start(i);    
            }
        }
        private void threadMethod(object n)
        {
            for (int i = 0; i < 100; i++)
            {
                lock (LockThis)
                {
                    flag++;
                    Console.WriteLine( flag.ToString());
                    if (flag >= 300)
                    {
                        Console.WriteLine("线程"+n.ToString()+"检测到flag已经达到目标数值,自动终结所有线程");
                        foreach (Thread t in threads)
                        {
                            t.Abort();
                        }
                    }
                    
                }
            }
        }
实际运行的时候,是这样的,总有几个线程没有被结束掉:
。。。。。。
295
296
297
298
299
300
线程2已经达到目标数值,自动终结所有线程
301
线程3已经达到目标数值,自动终结所有线程
302
线程8已经达到目标数值,自动终结所有线程


上面的代码出问题在什么地方呢?除了上面的用Lock,还有什么更好的方法呢?

6 个解决方案

#1


线程最好让它自行了断, 都去判断 flag  就可以了.

#2


终结的过程中有新线程启动,就是说终结300的时间片间隙启动了新线程咯

#3


1、明明只操作同一个变量,你却让每个线程都对它进行同样的监视和处理,而对所有线程的Abort()又几乎是同时发生的,这一瞬间每个人都在杀掉所有人,这是一个很不周全的逻辑,可以想象你的程序当flag为300时已经混乱成什么样子,很可怕

2、原则上不应在线程外结束它,这样会在线程内引发“正在终止线程”的异常,而你又没有对这些异常进行处理,所以会导致程序不会按照“看上去应该这样跑”的流程运行,举个例子:当有一个线程已经杀掉两个线程的时候,突然被别人给Abort了,这时就发生了异常,剩下的线程是不是就无法进行处理了?而同样的事情发生在每个线程中,我想这应该是关键所在。

3、你在Abort()时应当先判断这个线程对象是否IsAlive,这里同样可能引发异常。多线程本来就不安全,而你通篇没有一个异常处理,这样非常不负责任。

#4


引用 楼主 sug254te 的回复:
我想实现多个线程对同一个变量进行累加,当某个线程发现这个变量超过指定值比如300,


看到滥用线程的人我们会“绕着走”,因为一个团队开发的产品不能因为有人任性而垮掉(死掉)。

如果你确实需要修改一个变量,那么修改变量之前判断一下
if(abc<=300)
{
     .....修改它
}
不就完了嘛。儿你满脑子的都是光怪陆离的程序幻象,没有灭定的习惯。

#5


假设就算是“玩儿”线程,在你的 for 循环中,在 flag++ 语句之前,写
if (flag > 300) 
    return;

很简单的流程,这就完毕了,这是基本流程,不管有多少线程你都得写这个flag<300或者flag>300的判断才算是附和最基本的业务逻辑判断。

纠结 Abort 是多余的。连业务逻辑都没有写对,怎么可能写纯技术的代码呢?

#6


判断写在线程方法内

另外详细阅读MSDN上关于Abort的解释,可以解决你的疑惑。

#1


线程最好让它自行了断, 都去判断 flag  就可以了.

#2


终结的过程中有新线程启动,就是说终结300的时间片间隙启动了新线程咯

#3


1、明明只操作同一个变量,你却让每个线程都对它进行同样的监视和处理,而对所有线程的Abort()又几乎是同时发生的,这一瞬间每个人都在杀掉所有人,这是一个很不周全的逻辑,可以想象你的程序当flag为300时已经混乱成什么样子,很可怕

2、原则上不应在线程外结束它,这样会在线程内引发“正在终止线程”的异常,而你又没有对这些异常进行处理,所以会导致程序不会按照“看上去应该这样跑”的流程运行,举个例子:当有一个线程已经杀掉两个线程的时候,突然被别人给Abort了,这时就发生了异常,剩下的线程是不是就无法进行处理了?而同样的事情发生在每个线程中,我想这应该是关键所在。

3、你在Abort()时应当先判断这个线程对象是否IsAlive,这里同样可能引发异常。多线程本来就不安全,而你通篇没有一个异常处理,这样非常不负责任。

#4


引用 楼主 sug254te 的回复:
我想实现多个线程对同一个变量进行累加,当某个线程发现这个变量超过指定值比如300,


看到滥用线程的人我们会“绕着走”,因为一个团队开发的产品不能因为有人任性而垮掉(死掉)。

如果你确实需要修改一个变量,那么修改变量之前判断一下
if(abc<=300)
{
     .....修改它
}
不就完了嘛。儿你满脑子的都是光怪陆离的程序幻象,没有灭定的习惯。

#5


假设就算是“玩儿”线程,在你的 for 循环中,在 flag++ 语句之前,写
if (flag > 300) 
    return;

很简单的流程,这就完毕了,这是基本流程,不管有多少线程你都得写这个flag<300或者flag>300的判断才算是附和最基本的业务逻辑判断。

纠结 Abort 是多余的。连业务逻辑都没有写对,怎么可能写纯技术的代码呢?

#6


判断写在线程方法内

另外详细阅读MSDN上关于Abort的解释,可以解决你的疑惑。