线程同步经典问题,和尚挑水问题

某寺庙有小和尚、老和尚若干。庙内有一水缸、由小和尚提水入缸,供老和尚饮用。水缸可容纳10桶水,每次入水、取水都为1桶,且不可同时进行。水取自同一井中,水井口很小,每次只能容纳一只水桶取水。设水桶个数为3个。试写出小和尚和老和尚的函数,假设有5个小和尚提水入缸,5个老和尚取水喝(每隔一定时间取水一次),分别用不同的线程模拟小和尚和老和尚,使他们能同步进行。(每个和尚一个线程)

Var mutex1, mutex2, empty, full, count: semaphore;
mutex1:=1; mutex2:=1;
empty:=10; full:=0; count:=3;

process 小和尚:
begin
repeat
wait(empty);
wait(count);
wait(mutex1);
从井中取水;
signal(mutex1);
wait(mutex2);
送水入水缸;
signal(mutex2);
signal(count);
signal(full);
until false;
end
process 老和尚:
begin
repeat
wait(full);
wait(count);
wait(mutex2);
从缸中取水;
signal(mutex2);
signal(empty);
signal(count);
until false;
end

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static int n = 0;

        static object lockobj = new object();
        static void wt(object i)
        {
            Random r = new Random((int)i ^ (int)DateTime.Now.Ticks);
            Console.WriteLine("young monk " + i + " is started...");
            while (true)
            {
                lock (lockobj)
                {
                    if (n < 5)
                    {
                        n++;
                        Console.WriteLine("young monk " + i + " add, now have " + n);
                    }
                }
                Thread.Sleep(r.Next(3000, 5000));
            }
        }

        static void ct(object i)
        {
            Random r = new Random((int)i ^ (int)DateTime.Now.Ticks);
            Console.WriteLine("old monk " + i + " is started...");
            while (true)
            {
                lock (lockobj)
                {
                    if (n > 0)
                    {
                        n--;
                        Console.WriteLine("old monk " + i + " sub, now have " + n);
                    }
                }
                Thread.Sleep(r.Next(3000, 5000));
            }
        }
        static void Main(string[] args)
        {
            for (int i = 0; i < 5; i++)
            {
                Thread t1 = new Thread(new ParameterizedThreadStart(wt));
                t1.Start(i);
                Thread t2 = new Thread(new ParameterizedThreadStart(ct));
                t2.Start(i);
            }
        }

    }
}

young monk 0 is started...
old monk 3 is started...
young monk 1 is started...
old monk 0 is started...
old monk 2 is started...
old monk 4 is started...
young monk 4 is started...
young monk 2 is started...
young monk 3 is started...
old monk 1 is started...
young monk 0 add, now have 1
old monk 3 sub, now have 0
young monk 2 add, now have 1
young monk 3 add, now have 2
old monk 2 sub, now have 1
old monk 0 sub, now have 0
young monk 4 add, now have 1
young monk 1 add, now have 2
old monk 2 sub, now have 1
old monk 3 sub, now have 0
young monk 4 add, now have 1
old monk 4 sub, now have 0
young monk 0 add, now have 1
young monk 2 add, now have 2
young monk 3 add, now have 3
young monk 1 add, now have 4
old monk 1 sub, now have 3
old monk 3 sub, now have 2
old monk 2 sub, now have 1
old monk 0 sub, now have 0
young monk 0 add, now have 1
young monk 4 add, now have 2
old monk 4 sub, now have 1
young monk 3 add, now have 2
young monk 2 add, now have 3
young monk 1 add, now have 4
old monk 1 sub, now have 3
old monk 3 sub, now have 2
old monk 2 sub, now have 1
old monk 0 sub, now have 0
young monk 0 add, now have 1
young monk 3 add, now have 2
old monk 1 sub, now have 1
young monk 1 add, now have 2
young monk 4 add, now have 3
old monk 4 sub, now have 2
young monk 2 add, now have 3
old monk 3 sub, now have 2
young monk 3 add, now have 3
old monk 0 sub, now have 2
young monk 0 add, now have 3
old monk 2 sub, now have 2
old monk 1 sub, now have 1
young monk 1 add, now have 2
young monk 4 add, now have 3
old monk 4 sub, now have 2
old monk 3 sub, now have 1

小和尚取水的间隔时间和老和尚喝水的间隔时间是多少?

//经典线程同步互斥问题
#include
#include
#include

long g_nNum; //全局资源
unsigned int __stdcall Fun(void *pPM); //线程函数
const int THREAD_NUM = 10; //子线程个数

int main()
{
g_nNum = 0;
HANDLE handle[THREAD_NUM];

int i = 0;
while (i < THREAD_NUM) 
{
    handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);
    i++;//等子线程接收到参数时主线程可能改变了这个i的值
}
//保证子线程已全部运行结束
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);  
return 0;

}

unsigned int __stdcall Fun(void *pPM)
{
//由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来
int nThreadNum = *(int *)pPM; //子线程获取参数
Sleep(50);//some work should to do
g_nNum++; //处理全局资源
Sleep(0);//some work should to do
printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum);
return 0;
}