多线程程序中可能存在的问题(1)

  • Post author:
  • Post category:其他




摘要

多线程程序在处理公共变量的时候,要注意多线程之间可能存在的问题。在实际程序运行期间,由于各线程运行时间周期的存在差异,这可能导致不同的线程在读取相同的内存地址数据(公有变量数据)时,可能存在多个线程读取到相同的数值。特别是系统繁忙的时候,这种问题发生的概率将变高。



具体实例

下列函数在处理字典a的数据时,由于启动的多个线程都会在启动之后调用主线程的公共变量k,v。此时,由于主线运行速度相对比较慢,那么这会导致不同的线程程读到了相同的值。

func TestMultiThreadProblem(t *testing.T){
	a:=make(map[int]int)
	for i:=0;i<10;i++{
		a[i]=100-rand.Int()
	}
	for k,v:=range a{
		go func(){
			time.Sleep(1*time.Microsecond)
			log.Println(k,v)
		}()
		time.Sleep(1*time.Microsecond)
	}
	time.Sleep(10*time.Second)
}
  • 执行结果如下

    在这里插入图片描述

    按照上面的结果,红框部分出现了两个线程读取到同一个值的情况。

  • 原因分析

    这是因为计算机线程的启动是无序启动,且主线程的执行相对比较慢,导致变量k,v变化的速度较慢。故在一个时间区间



    t

    t






    t





    内,k,v的值被多个线程同时访问,出现了最终出现两个线程读取到同一个值的情况。

  • 解决办法

    在创建线程的同时,将所需数据直接作为参数传递的线程的函数中,线程运行过程中不再向共有变量读取数值,具体代码如下:

func TestMultiThreadProblem(t *testing.T){
	a:=make(map[int]int)
	for i:=0;i<10;i++{
		a[i]=100-rand.Int()
	}
	for k,v:=range a{
		go func(k1,v1 int){
			time.Sleep(1*time.Microsecond)
			log.Println(k1,v1)
		}(k,v)
		time.Sleep(1*time.Microsecond)
	}
	time.Sleep(10*time.Second)
}



结论

我们一定要注意线程在处理公共变量时可能存在的安全问题。系统在正常提供服务的时候这些问题很少会出现,但是如果系统处于繁忙状态,这些问题发生的概率会明显增高。



版权声明:本文为qq_22881345原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。