重大发现(愚以为)!深拷贝与同步互斥的异曲同工

梦里开天 2009-10-09 10:07:31
今天写了个测试程序,发现在不同线程中调用同一个函数时,如果参数是引用类型(数组实例),数组会被相互干扰。
我的解决方法:
1:同步互斥:经典的四种方法(加锁、互斥量、符号、信号) 这就不说了
2:深拷贝:
 public class tool1:ICloneable

实现接口
    #region ICloneable 成员

public object Clone()
{
tool1 newSession = new tool1(n);
newSession.n = n;//
return newSession;
//throw new Exception("The method or operation is not implemented.");
}

#endregion

我的测试结果是:
2种方法都可实现,但是同步互斥是比较浪费时间的。
深拷贝是比较浪费空间,但是速度很快。

欢迎大家指正,是不是有什么没有考虑到。
...全文
206 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
微创社(MCC) 2009-10-13
  • 打赏
  • 举报
回复
QQ
24K純帥 2009-10-13
  • 打赏
  • 举报
回复
顶下,好帖。。
cxxylce0 2009-10-13
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 sp1234 的回复:]
引用 1 楼 wartim 的回复:
但是你要知道,深拷贝后就是2个对象了,对2个对象来说,本来就没有同步互斥的问题,而且互斥是针对访问共享的唯一对象,而同步是几个线程间的次序问题,比如要先写入才能读出


我基本同意这种说法。

有些资料,甚至微软为了推销F#的文档,鼓吹什么拷贝可以解决同步问题。纯粹是自欺欺人。

为什么会产生“相互干扰”现象?不外乎两种原因:
1. 根本不应该修改对象。那么你需要测试系统来发现修改对象的逻辑bug,这样就是不用拷贝也不会出错,因为你的程序并不会修改对象。

2. 运行中必须实时修改对象,来同步多个业务逻辑的执行次序。那么所谓深拷贝系统就完蛋了。


所以,我们需要的是一个测试系统可以在实际发布系统之前就测试出所谓线程不安全,或者有(类似于微软正在研究而没有发布的一些系统)对内存进行可靠的类似数据库事务的保护(编程要求很少)。在复杂的系统中拼命地地拷贝大量环境数据放到堆栈上,可能只能算作一个比较学术的做法。
[/Quote]

如何解决多线程同步问题?
开2个进程
再不行买2台电脑。

哈哈,算不算重大发现?
十八道胡同 2009-10-12
  • 打赏
  • 举报
回复
一个浪费时间 ,一个浪费空间,
要不弄成静态的?省的new,不过弊端也很大。。
梦里开天 2009-10-12
  • 打赏
  • 举报
回复
在顶一下
梦里开天 2009-10-10
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 shrinerain 的回复:]
同步问题是为了解决访问"同一个对象"造成的数据不完整.

copy就是copy, 为了获得"多个对象".


这两个怎么会扯在一块了?


[/Quote]
在某种情况下牺牲空间换时间
十八道胡同 2009-10-10
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 shrinerain 的回复:]
同步问题是为了解决访问"同一个对象"造成的数据不完整.

copy就是copy, 为了获得"多个对象".


这两个怎么会扯在一块了?


[/Quote]
异曲同工 ,结果都是原实例的数组没被修改
shrinerain 2009-10-10
  • 打赏
  • 举报
回复
同步问题是为了解决访问"同一个对象"造成的数据不完整.

copy就是copy, 为了获得"多个对象".


这两个怎么会扯在一块了?

梦里开天 2009-10-10
  • 打赏
  • 举报
回复
不能这样沉了
梦里开天 2009-10-09
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 v68v6 的回复:]
此贴极有可能被推荐
[/Quote]
”作为典型错误,很成功?“ 哈哈 我只是测试中发现,所以想到了,似乎有些不妥,但是感觉还是看在什么情况下,具体问题具体分析。
梦里开天 2009-10-09
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 sp1234 的回复:]
引用 1 楼 wartim 的回复:
但是你要知道,深拷贝后就是2个对象了,对2个对象来说,本来就没有同步互斥的问题,而且互斥是针对访问共享的唯一对象,而同步是几个线程间的次序问题,比如要先写入才能读出


我基本同意这种说法。

有些资料,甚至微软为了推销F#的文档,鼓吹什么拷贝可以解决同步问题。纯粹是自欺欺人。

为什么会产生“相互干扰”现象?不外乎两种原因:
1. 根本不应该修改对象。那么你需要测试系统来发现修改对象的逻辑bug,这样就是不用拷贝也不会出错,因为你的程序并不会修改对象。

2. 运行中必须实时修改对象,来同步多个业务逻辑的执行次序。那么所谓深拷贝系统就完蛋了。


所以,我们需要的是一个测试系统可以在实际发布系统之前就测试出所谓线程不安全,或者有(类似于微软正在研究而没有发布的一些系统)对内存进行可靠的类似数据库事务的保护(编程要求很少)。在复杂的系统中拼命地地拷贝大量环境数据放到堆栈上,可能只能算作一个比较学术的做法。
[/Quote]
你可真是个热心人,上次c/s系统的负载预测就是有你的解说和推断,最后越来越清晰。
我这里的问题主要是多线程中单个线程多次接收数据,如果接收太快,上次还未处理,数据就被覆盖了,我不想这样,系统其实不会这么频繁接收,所以没有使用缓冲区,而是直接覆盖数据,所以我想用深拷贝把未处理的处理,而这样即使新来的数据很快到来,会有新的事件触发,再次处理。
当然这里有个问题,就是如果tcp本身粘包那我可能就没办法了,但是我的程序中数据处理需要时间相对长一些,所以我担心的是旧数据被新数据覆盖。
  • 打赏
  • 举报
回复
在你的系统中可以插入断言,一旦发现数据被修改了,就抛出异常。这样成千上万次自动化测试时总会发现线程不安全问题,并且根据异常堆栈的调试可以知道哪一个线程修改了数据。

其实只有很少的情况下,我们临时使用序列化、反序列化来复制对象,所谓的“避免互斥问题”,这种方法多年前就有。只是我们很谨慎地使用就是了。
天乐 2009-10-09
  • 打赏
  • 举报
回复
楼主这番思考的精神值得赞扬

不过就事论事的说,想歪了

深拷贝用作线程互斥的解决方案本身有点南辕北辙

另外,string在C#中是引用类型,而非值类型,仅仅是用起来“像”是值类型一样
V68V6 2009-10-09
  • 打赏
  • 举报
回复
此贴极有可能被推荐
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 wartim 的回复:]
但是你要知道,深拷贝后就是2个对象了,对2个对象来说,本来就没有同步互斥的问题,而且互斥是针对访问共享的唯一对象,而同步是几个线程间的次序问题,比如要先写入才能读出
[/Quote]

我基本同意这种说法。

有些资料,甚至微软为了推销F#的文档,鼓吹什么拷贝可以解决同步问题。纯粹是自欺欺人。

为什么会产生“相互干扰”现象?不外乎两种原因:
1. 根本不应该修改对象。那么你需要测试系统来发现修改对象的逻辑bug,这样就是不用拷贝也不会出错,因为你的程序并不会修改对象。

2. 运行中必须实时修改对象,来同步多个业务逻辑的执行次序。那么所谓深拷贝系统就完蛋了。


所以,我们需要的是一个测试系统可以在实际发布系统之前就测试出所谓线程不安全,或者有(类似于微软正在研究而没有发布的一些系统)对内存进行可靠的类似数据库事务的保护(编程要求很少)。在复杂的系统中拼命地地拷贝大量环境数据放到堆栈上,可能只能算作一个比较学术的做法。
梦里开天 2009-10-09
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lnwuyaowei 的回复:]
微软的string类型就是楼主这样处理的.
当然是线程安全,但是.....
[/Quote]
string类型在c#中本身就是值类型,而不是引用。
梦里开天 2009-10-09
  • 打赏
  • 举报
回复
我主要是把从客户端接收到数据即时获取,防止下次接收的数据更改(我没设缓冲区,是一次一次地接收)
lnwuyaowei 2009-10-09
  • 打赏
  • 举报
回复
微软的string类型就是楼主这样处理的.
当然是线程安全,但是.....
wartim 2009-10-09
  • 打赏
  • 举报
回复
但是你要知道,深拷贝后就是2个对象了,对2个对象来说,本来就没有同步互斥的问题,而且互斥是针对访问共享的唯一对象,而同步是几个线程间的次序问题,比如要先写入才能读出

111,120

社区成员

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

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

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