多线程并发全局变量错乱问题。

时间:2022-06-25 17:56:44
情况:3个线程,同时调用一个方法,但是这个方法中的数据库连接字段是不一样的。所以设定这个连接字段为全局变量。

结果:结果,我同时3个线程并发。第一个和第三个连接数据库的字符串都是正确的,方法执行结果页没有问题,而第二个却是第三的连接字符串,导致我无法访问操作第二个不同的数据库。 另外,我加锁了。


部分代码:


     Thread[] threads = new Thread[connectlist.Count];

            int i = 0;
            while (i < connectlist.Count)  //现在就3个,每个都有前面赋值。
            {
               
                _oracleconnect = "";  //此为连接Oracle的字符串,全局变量
                _oracleconnect = connectlist[i];
                
            
                try
                {
                    threads[i] = new Thread(new ThreadStart(this.testlock));
                    threads[i].Start();
                    Thread.Sleep(100);

                }
                catch (Exception ex)
                {
                    _log.WriterErroreLog(ex);
                }
                i++; 
            }

   private void testlock()
        {
            lock (obj)
            {
                SendMoreGrainTemp(); // 此为公用方法,其中连接数据库,操作数据库都在这个方法里。

            }
        }





希望有人能帮我解惑下,不知道为什么,第二个线程的赋值字符串总是第三个。

10 个解决方案

#1


线程是异步执行,你外循环的i的加减不受线程影响

#2


你线程是用来干什么的,连接数据库的么?那你可以直接写一个类啊,线程调用的方法都写在一个类里面,在new这个类的时候,把线程打开~

#3


那请问如果改呢?在方法里执行完毕后++?

引用 1 楼 xdashewan 的回复:
线程是异步执行,你外循环的i的加减不受线程影响

#4


同时对N个oracle数据库,推送数据,每个数据库地址不同。

引用 2 楼 superior_yong 的回复:
你线程是用来干什么的,连接数据库的么?那你可以直接写一个类啊,线程调用的方法都写在一个类里面,在new这个类的时候,把线程打开~

#5


这种情况使用哪个数据库连接一定要随上下文传进去的,至于你用方法参数还是属性还是Thread.SetData都可以

如果没办法传进去,比如SendMoreGrainTemp根本不是为多线程的场景设计的,那你在外边就只有一件事可做,就是保证同时只在一个线程里调用它

#6


引用 4 楼 moranhuoshou 的回复:
同时对N个oracle数据库,推送数据,每个数据库地址不同。

Quote: 引用 2 楼 superior_yong 的回复:

你线程是用来干什么的,连接数据库的么?那你可以直接写一个类啊,线程调用的方法都写在一个类里面,在new这个类的时候,把线程打开~



在类中定义一个属性或者变量存储数据库地址不就好了么

#7


引用 3 楼 moranhuoshou 的回复:
那请问如果改呢?在方法里执行完毕后++?

private void testlock(int index)
{
          _oracleconnect = connectlist[index];
          。。。。。。。。。
}
i作为参数传进去,在里面取字符串

#8


你的线程根本没有参数
所以线程方法根本不知道该上哪里去找自己对应的字符串
你应该给线程传递参数

private void testlock(object str)
调用的时候
threads[i].Start(string);//每个线程传入不同的字符串

#9


private void testlock( object state)
{
    string connectionString = (string)state;
    lock (obj)
    {
        SendMoreGrainTemp( connectionString);
    }
}

// 不用全局变量,而是把线程需要的‘参数’传递进去。
threads[i] = new Thread(nthis.testlock);
threads[i].Start( connectlist[i]);

#10


OK,OK。问题解决。错误原因正如1楼所说,所以才造成了,连接字符串总是错乱的原因。我本以为,一个变量而已,Lock主就行了,没想到啊。。。。。早知道就传参数了。。。。。类似9楼就行,上面基本都是说在点子上。谢谢各位指教。

#1


线程是异步执行,你外循环的i的加减不受线程影响

#2


你线程是用来干什么的,连接数据库的么?那你可以直接写一个类啊,线程调用的方法都写在一个类里面,在new这个类的时候,把线程打开~

#3


那请问如果改呢?在方法里执行完毕后++?

引用 1 楼 xdashewan 的回复:
线程是异步执行,你外循环的i的加减不受线程影响

#4


同时对N个oracle数据库,推送数据,每个数据库地址不同。

引用 2 楼 superior_yong 的回复:
你线程是用来干什么的,连接数据库的么?那你可以直接写一个类啊,线程调用的方法都写在一个类里面,在new这个类的时候,把线程打开~

#5


这种情况使用哪个数据库连接一定要随上下文传进去的,至于你用方法参数还是属性还是Thread.SetData都可以

如果没办法传进去,比如SendMoreGrainTemp根本不是为多线程的场景设计的,那你在外边就只有一件事可做,就是保证同时只在一个线程里调用它

#6


引用 4 楼 moranhuoshou 的回复:
同时对N个oracle数据库,推送数据,每个数据库地址不同。

Quote: 引用 2 楼 superior_yong 的回复:

你线程是用来干什么的,连接数据库的么?那你可以直接写一个类啊,线程调用的方法都写在一个类里面,在new这个类的时候,把线程打开~



在类中定义一个属性或者变量存储数据库地址不就好了么

#7


引用 3 楼 moranhuoshou 的回复:
那请问如果改呢?在方法里执行完毕后++?

private void testlock(int index)
{
          _oracleconnect = connectlist[index];
          。。。。。。。。。
}
i作为参数传进去,在里面取字符串

#8


你的线程根本没有参数
所以线程方法根本不知道该上哪里去找自己对应的字符串
你应该给线程传递参数

private void testlock(object str)
调用的时候
threads[i].Start(string);//每个线程传入不同的字符串

#9


private void testlock( object state)
{
    string connectionString = (string)state;
    lock (obj)
    {
        SendMoreGrainTemp( connectionString);
    }
}

// 不用全局变量,而是把线程需要的‘参数’传递进去。
threads[i] = new Thread(nthis.testlock);
threads[i].Start( connectlist[i]);

#10


OK,OK。问题解决。错误原因正如1楼所说,所以才造成了,连接字符串总是错乱的原因。我本以为,一个变量而已,Lock主就行了,没想到啊。。。。。早知道就传参数了。。。。。类似9楼就行,上面基本都是说在点子上。谢谢各位指教。