public partial class Form1 : Form
{ Thread thread = null;
Thread th = null;
public Form1()
{
InitializeComponent();
thread = new Thread(time);
th = new Thread(show); thread.IsBackground = true;
thread.Start();
th.Start();
} int i = 0;
ArrayList arr = new ArrayList ();
public void time()
{ while (true)
{
Thread.Sleep(100);
i += 5;
arr.Add(i);
label1.Text = i.ToString();
} } public void show()
{
while (true)
{
Thread.Sleep(100);
if (arr.Count != 0)
{
int j = (int)arr[0];
label3.Text = j.ToString();
arr.RemoveAt(0);
}
label2.Text = i.ToString();
}
}
}
这里 需要对 time类中的 arr 加lock吗?我感觉 加不加 效果都一样。 并不会出现下面所说的情况,这个是什么原因呢??网上资料说“在多线程的程序中经常会遇到,多个线程要对一个对象进行操作的情况这样的话如果没有一个线程的控制的话一定会造成数据的损坏。比如两个现成要对同一个数组进行操作一个需要对数组进行加操作而另一个则要进行减操作。在这种情况下如果没有lock那就会很容易的出现超出数组界限的事情。”
那我去掉 Sleep(100)是不是 就要 使用 lock了呢??
我也在考虑程序的正确性,可是我不知道 什么样的才是规范的~那就是说需要加 lock ?
lock(arr)
{
arr.Add(...);
}
或者用 ArrayList.Synchronized 把你的ArrayList包装成线程同步的集合~
恩恩, 还有个问题就是 lock(arr),之后,其他线程就不能对 arr进行数据操作了呢??看了好多遍 lock还是不明白这个……我实验的结果:其它线程还是可以对 arr进行操作的。求解
{
if (_money >= money)
_money -= money;
}
现在是没有同步的,如果有两个线程,就像有两个人同时取款100元。
那么结果如何?两个人都可以取出100元!银行破产了!那么同步的代码:
private object _lockObj = new Object();
private void GetMoney(int money)
{
lock(_lockObj)
{
if (_money >= money)
_money -= money;
}
}
因为这里同步了,所以_money不可能同时被两个线程做减法操作,一定是一个减完,另一个再减。
这样判断上就不会出错了,因为第二个进来的线程判断_money已经小于money了。
但是每个线程执行的操作是唯一的,不重复的
也就是说,一个线程,只管添加,一个线程只管移除
这2个操作本身并不存在冲突假设2个线程同时添加和删除,程序不会抛出异常,所以就这个程序来说不需要加锁
如果有2个线程都在执行删除操作
这时,如果arr只有1个对象
而2个线程都在执行
arr.RemoveAt(0);只有一个会成功,而另一个线程就抛出异常了
lock(arr)
{}
的代码块之后第二个线程如果碰到 lock(arr),则会阻塞(暂停)不进入{}中
直到第一个线程走出lock(arr){}之后,第二个线程才会进入{}中运行
并且在操作前判断了数组长度必须大于0,这个时候是不会出现数组越界的问题的
至少不会出现下标越界
有可能添加操作的线程没有进行上标判断而出现上标越界
呵呵,没事,我刚才的话只就这个程序来说的
因为原理LS几位朋友都已经解释的很清楚了,我没有再说我个人比较倾向,理论和实践结合的论述方式
这样可以使LZ更加容易理解当时作为初级程序员来说必须先有"线程同步"的想法
等完全理解后,
如果可以判断代码绝对不会出现异常的时候,少一些lock也可以加快一些效率不是吗?就好比unsafe { }代码块,明知道是不安全的,为了效率还是会用到,呵呵~~~~
这个东西没必要取巧,规规矩矩lock就是了,能以逻辑判断的情况下,比反复试错要更精确,反复测试这种方法不适用于和概率有关的问题。
如果要采取更快速的锁机制,干脆就不用arraylist,自定义一个数组,对写和读的当前索引进行原子操作可以稍微提高速度,同时编程难度也增加了很多。
这个我以前没有考虑过,我一直以为.net的数组都是有默认线程同步的处理的...因为一直没有出错过
也就没有深究了,下次可以reflector反编译后看一下...
{
for (int i = 0; i < 100; i++)
{
i++;
}
}public static void bbb()
{
for (int i = 0; i < 100; i++)
{
i--;
}
}
[STAThread]
static void Main()
{ Thread t1 = new Thread(aaa);
Thread t2 = new Thread(aaa);
Thread t3 = new Thread(bbb);
Thread t4 = new Thread(bbb);
t1.Start();
t2.Start();
t3.Start();
t4.Start(); while (t1.IsAlive
&& t2.IsAlive
&& t3.IsAlive
&& t4.IsAlive)
{
Thread.Sleep(100);
Application.DoEvents();
}
}
这样的操作会不会出错呢??
我以前的理解一直就是,.net默认做了同步的处理......
确实会出问题 for (int i = 0; i < 100; i++)
{
Thread t1 = new Thread(aaa);
Thread t2 = new Thread(bbb);
t1.Start();
t2.Start();
}
在如此极限的情况了200次...终于出问题了..ii=1..总算了却了一件心事...
for (int i = 0; i < 1000; i++)
{
new Thread(aaa).Start();
new Thread(aaa).Start();
new Thread(aaa).Start();
new Thread(bbb).Start();
new Thread(aaa).Start();
new Thread(bbb).Start();
new Thread(bbb).Start();
new Thread(bbb).Start();
}
哈哈哈哈哈哈哈哈哈啊哈哈哈哈哈哈哈
我疯啦....终于每次都出问题了!!!!
不sleep 全部线程结束后打印ii