多线程数据错乱问题

猴子写代码 2015-03-11 09:17:40
我有3个线程A,B,C

这三个线程都会把不同的数据写到同一个数据库中不同的表

各线程对应的数据为:

A:1------->数据库T1表
B:2------->数据库T2表
C:3------->数据库T3表

问题:写到各自对应的数据库后,发现数据不对,比如A线程应该把1写到T1表,但现在可能是T1和T2都是1,T3正确。这种情况10次操作会出现1,2次。请问线程之间数据会影响?
...全文
696 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
於黾 2015-03-11
  • 打赏
  • 举报
回复
放出你线程的代码来,是否都执行的同一个函数并且没有参数,所以其实都是运行的同一个逻辑? 简单的检测方法: 先把另外两个线程注释掉,不让它执行,只执行其中一个线程,看结果
SPFarmer 2015-03-11
  • 打赏
  • 举报
回复
往不同的表写,线程之间是不会互相影响的。 因此需要检查你的业务逻辑,是不是有问题。
xian_wwq 2015-03-11
  • 打赏
  • 举报
回复
为了排查问题 建议先不要多线程,把写入数据入队列 由单独线程从队列中取数操作入库 这样可以检测出业务逻辑有没有bug
  • 打赏
  • 举报
回复
引用 16 楼 jeabo 的回复:
我是一个线程一个对象,线程的执行方法也在这个对象里面,执行方法都是调用的对象里面的属性。这个子线程之间没有共享的资源吧
线程执行的方法(的源代码)本身才访问了数据,跟你有几个对象无关。 比如说有两个女人无意中嫁了同一个丈夫,你不能说她们(两个独立的对象)有毛病,其实是那个男的有毛病才对。
猴子写代码 2015-03-11
  • 打赏
  • 举报
回复
引用 14 楼 sp1234 的回复:
不法 --> 无法 随便举两个例子。比如说有人定一个
private static DbConnection conn;
变量,这一看就知道经不起多线程程序考验。 再比如说代码
foreach( var x in list)
{
    启动线程处理(x);
}
这显然也会出现问题的,因为变量 i 是被多线程所共享访问的。
我是一个线程一个对象,线程的执行方法也在这个对象里面,执行方法都是调用的对象里面的属性。这个子线程之间没有共享的资源吧
於黾 2015-03-11
  • 打赏
  • 举报
回复
用到了多线程,线程函数却不给参数 我很难想象这东西会不出错
  • 打赏
  • 举报
回复
不法 --> 无法 随便举两个例子。比如说有人定一个
private static DbConnection conn;
变量,这一看就知道经不起多线程程序考验。 再比如说代码
foreach( var x in list)
{
    启动线程处理(x);
}
这显然也会出现问题的,因为变量 i 是被多线程所共享访问的。
於黾 2015-03-11
  • 打赏
  • 举报
回复
多线程不是顺序执行的 你没法保证每个线程的执行顺序 所以有时候执行结果是这样,其他时候执行结果是那样,这太正常了
  • 打赏
  • 举报
回复
引用 楼主 jeabo 的回复:
问题:写到各自对应的数据库后,发现数据不对,比如A线程应该把1写到T1表,但现在可能是T1和T2都是1,T3正确。这种情况10次操作会出现1,2次。请问线程之间数据会影响?
任何变量都是有作用域的,如果你滥用了它,自然就会被不同的线程访问到,从而产生你根本不法预想到的“任意随机发生”的错乱。所以如果你的数据错了,那么就看看你为某些变量定义的作用域是不是太“托大”了。
於黾 2015-03-11
  • 打赏
  • 举报
回复
引用 10 楼 jeabo 的回复:
我现在的情况是有时候出现,大部分情况下是不出现的,这种情况很难去查,数据都是固定死的,如果有逻辑性错误,应该每次都错的
那可不一定
猴子写代码 2015-03-11
  • 打赏
  • 举报
回复
引用 7 楼 Z65443344 的回复:
你如何确保里面的属性是不一样的呢?
引用 8 楼 qldsrx 的回复:
1、检查是否有全局变量的存在 2、日志记录每个线程的数据和操作的表名,附带预期的数据和表名前缀做对比。
我现在的情况是有时候出现,大部分情况下是不出现的,这种情况很难去查,数据都是固定死的,如果有逻辑性错误,应该每次都错的
於黾 2015-03-11
  • 打赏
  • 举报
回复
根据楼主的描述 线程函数里实例化类,然后使用类内部的函数进行操作 而线程函数本身没有参数 楼主以为这样做,不同的实例,属性值应该不一样 但是我是没看出为什么会不一样,都一样才是对的
qldsrx 2015-03-11
  • 打赏
  • 举报
回复
1、检查是否有全局变量的存在 2、日志记录每个线程的数据和操作的表名,附带预期的数据和表名前缀做对比。
於黾 2015-03-11
  • 打赏
  • 举报
回复
你如何确保里面的属性是不一样的呢?
猴子写代码 2015-03-11
  • 打赏
  • 举报
回复
引用 5 楼 Z65443344 的回复:
是每个线程创建一个类,还是每个类里创建线程? 如果是线程创建类,那么虽然是3个不同的实例,但是参数肯定还都是一样的了
类是同一个类,实例化的对象不一样,里面的属性也不一样
於黾 2015-03-11
  • 打赏
  • 举报
回复
是每个线程创建一个类,还是每个类里创建线程? 如果是线程创建类,那么虽然是3个不同的实例,但是参数肯定还都是一样的了
猴子写代码 2015-03-11
  • 打赏
  • 举报
回复
放出你线程的代码来,是否都执行的同一个函数并且没有参数,所以其实都是运行的同一个逻辑? 简单的检测方法: 先把另外两个线程注释掉,不让它执行,只执行其中一个线程,看结果 执行方法放到一个类中的,每个线程都会创建一个该类的对象,运行的逻辑一样,只是有些变量不一样
          TaskRun theRun = new TaskRun(RunType.DiffSourceCheck, htPara);
            theRun.SourceNodeDBInfo = SourceNode[0];
            theRun.TargetNodeDBInfo = theDataSource;

            listNode.Add(theDataSource.DataSourceNodeCode + "," + theDataSource.DataSourceName);

            theRun.CheckDataSource = CheckDataSource;
            theRun.ThreadID = Guid.NewGuid().ToString();
            theRun.ListTaskItem = (from a in theCurTaskInfo.TaskItemList where a.IsSelect select a).ToList<TaskItemInfo>();
            theRun.RunnerSuccess += new RunnerEvent(TaskRunnerSuccessEvent);
            theRun.RunnerFailure += new RunnerEvent(TaskRunnerFailureEvent);
            theRun.SysParameter = SysParameter;
            System.Threading.Thread theThread = new System.Threading.Thread(new System.Threading.ThreadStart(theRun.RunTask));
            theThread.Name = theRun.ThreadID;

            ListAllThread.Add(theThread);
上面的theDataSource是不一样的

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧