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

摘要

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

具体实例

下列函数在处理字典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)
}

结论

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

经验分享 程序员 微信小程序 职场和发展