我想通过循环10次,对同一方法运行10个线程,但限制同时运行的线程为3个,其余等待。但我运行了好多好多次,总是不能完成10个线程,有时8个,有时9个。想了好久就是不明白。可能旁观者清,大家看看。刚开始编程,左拼右凑的,见笑了 :)请高手指点一下菜鸟,不胜感激!!
using System;
using System.Threading;public class T
{
public int chk;
public int i;
public int num = 0;
public T(int a,int b)
{
chk = a;
i = b;
} public void go()
{
Monitor.Enter(this);
chk++;
Monitor.Pulse(this); //每进行完一个线程,激活一个等待的线程
Monitor.Exit(this);
num++;
Console.WriteLine("#"+num+"=done=i:" + i+"==chk:"+chk); //用#标识
}
}public class A
{
public static void Main()
{
T b = new T(3,0); //初始化chk=3,i=0
int nums = 0;
for(;b.i<10;b.i++) //循环10次,产生10个线程
{
Monitor.Enter(b);
ThreadStart myThreadDelegate = new ThreadStart(b.go);
Thread myThread = new Thread(myThreadDelegate);
Console.WriteLine("in==i:" + b.i+"==chk:"+b.chk);
myThread.Start(); //线程调用go方法
b.chk--;
if(b.chk <= 0) //限制同时进行的线程为3个,当达到3时等待
{
nums++;
Console.WriteLine("@@@@"+nums+"wait==i:" + b.i+"==chk:"+b.chk);//用@标识
Monitor.Wait(b);
}
}
Console.WriteLine("F-END==i:" + b.i+"==chk:"+b.chk);
}
}
数一下#done的,总是没有10个,就是说没有10个线程完成,可明明循环了10次,为什么啊,头好大
using System;
using System.Threading;public class T
{
public int chk;
public int i;
public int num = 0;
public T(int a,int b)
{
chk = a;
i = b;
} public void go()
{
Monitor.Enter(this);
chk++;
Monitor.Pulse(this); //每进行完一个线程,激活一个等待的线程
Monitor.Exit(this);
num++;
Console.WriteLine("#"+num+"=done=i:" + i+"==chk:"+chk); //用#标识
}
}public class A
{
public static void Main()
{
T b = new T(3,0); //初始化chk=3,i=0
int nums = 0;
for(;b.i<10;b.i++) //循环10次,产生10个线程
{
Monitor.Enter(b);
ThreadStart myThreadDelegate = new ThreadStart(b.go);
Thread myThread = new Thread(myThreadDelegate);
Console.WriteLine("in==i:" + b.i+"==chk:"+b.chk);
myThread.Start(); //线程调用go方法
b.chk--;
if(b.chk <= 0) //限制同时进行的线程为3个,当达到3时等待
{
nums++;
Console.WriteLine("@@@@"+nums+"wait==i:" + b.i+"==chk:"+b.chk);//用@标识
Monitor.Wait(b);
}
}
Console.WriteLine("F-END==i:" + b.i+"==chk:"+b.chk);
}
}
数一下#done的,总是没有10个,就是说没有10个线程完成,可明明循环了10次,为什么啊,头好大
1.你若想真的看到同步的情况,可以具体考虑一下:go方法执行5秒钟,for循环1秒钟循环一次,这个可以考虑用Thread.Sleep(1000);放到for语句块的第一句,或者用Timer来实现。这样一步一步你可以看得很清楚。2.加锁时,是在线程对互斥资源访问前加锁,在你的程序里,完全看不出来是对什么加锁,你把加锁的语句放到了go方法里面去了,因为go方法里没有涉及到互斥资源,看得出,你的本意是在对go方法加锁,是吗?如果是,你的做法就不对了。
循环最后加上Monitor.Exit(b);
否则有死锁
就目前我对你这段程序的多次调试和理解后,我认为,加上Monitor.Exit(b);也不行,程序根本就不是按照你的原意在执行,至于为什么,我也不知道,我根本没法理解你的思维,不过,我可以这样来实现它,一会给出代码。
愿意和你谈一下,加我 QQ4896536 附言:.NET
using System.Threading;public class T
{
public int chk; //互斥资源数
public int i; //循环层次
public int num = 0; //线程计数,将以0为基数
public bool blBlock = false; //用于判断有无阻塞的线程
public T(int a,int b)
{
chk = a;
i = b;
} public void go()
{
int i = 0;
i = Interlocked.Increment( ref num ) - 1;
Console.WriteLine("$ Running Thread-" + i +" .");
Thread.Sleep(2000); //相当于运行一秒钟
Console.WriteLine("# Complete Thread-" + i +" ."); if( blBlock == true )
A.synchro.Set(); //
}
}public class A
{
static public ManualResetEvent synchro = null; public static void Main()
{
T b = new T( 3, 0 ); //初始化chk=3,i=0
synchro = new ManualResetEvent(false);
//Thread MainThread = Thread.CurrentThread;
for(b.i = 0; b.i<10; b.i++) //循环10次,产生10个线程
{ ThreadStart myThreadDelegate = new ThreadStart(b.go);
Thread myThread = new Thread(myThreadDelegate); if( b.chk > 0)//判断资源数目
{
b.chk --;
Console.WriteLine("* Call Thread-"+b.i+". But Not in the Thread-"+b.i+" .");
myThread.Start(); //
}
else
{
Console.WriteLine("Not enough resoucre! Block to start Thread-"+ b.i+" !!!");
b.blBlock = true;
synchro.WaitOne(); //for循环被挂起,即当前线程被阻塞
Console.WriteLine("* Call Thread-"+b.i+". But Not in the Thread-"+b.i+" .");
myThread.Start();
}
}
Console.WriteLine("End of for-Loop");
}
}/* 1. 我的想法是把b.chk作为有限个互斥资源,本例中为3个
* 2. 重写了你的for循环和go方法
* 3. 在for循环中,资源没有时,阻塞!//该程序已经测试通过
* */
using System.Threading;public class T
{
public int chk; //互斥资源数
public int i; //循环层次
public T(int a,int b)
{
chk = a;
i = b;
} public void go()
{
//首先对资源进行判断与分配,这个过程必须互斥
Monitor.Enter( chk );
if ( chk > 0 )
{
chk --;
}
Monitor.Exit ( chk );
//分配到资源,开始后面的执行 Console.WriteLine("$ Running Thread-" + i +" .");
Thread.Sleep(2000); //相当于运行两秒钟
Console.WriteLine("# Complete Thread-" + i +" .");
//执行完毕,开始释放资源
Monitor.Enter( chk );
chk ++;
Monitor.Exit( chk );//释放资源
Console.WriteLine("~ Release resource from Thread-"+i+" .");
}
}public class A
{
static public ManualResetEvent synchro = null; public static void Main()
{
T b = new T( 3, 0 ); //初始化chk=3,i=0
for(b.i = 0; b.i<10; b.i++) //循环10次,产生10个并发线程
{
ThreadStart myThreadDelegate = new ThreadStart(b.go);
Thread myThread = new Thread(myThreadDelegate); Console.WriteLine("* Call Thread-"+b.i+". But Not in the Thread-"+b.i+" .");
myThread.Start();
}
Console.WriteLine("End of for-Loop");
}
}/* 1. 同时并发10个go方法
* 2. go方法自身判断资源,决定是否执行或阻塞//已经测试通过
* *///我QQ没有收到系统消息啊,你是不是加错人了,中午12点后我一般在线上
{
private static int lockCount = 0;
public static void Initialize(int count)
{
this.lockCount = count;
}
public static void Wait()
{
while(this.lockCount <= 0)
{
Thread.Sleep(18);
}
this.lockCount--;
} public static void Signal()
{
this.lockCount++;
}
}
好了,有了这个类,你就可以这样做了。Locker.Initialize(3); // 仅 3 个线程同时运行// 线程函数像这样写。
private void ThreadFunc()
{
Locker.Wait();
...
Locker.Signal();
}呵呵,上面用的就是操作系统上的信号量方法。可以试一试。
Semaphore.Initialize(3);private void ThreadFunc()
{
Semaphore.Wait();
...
Semaphore.Signal();
}
当并发多个线程时,你可以保证一个Wait()方法的原子性?服了U了!如果多个线程同时对this.lockCount <= 0进行判断呢?