本帖最后由 hehe04 于 2012-8-26 19:21 编辑
这两天学习多线程的内容,其中有一个很重要的概念,那就是互锁。当多个线程在运行时需要使用到同一资源,那么就需要使用互锁。例如,提示用户输入一句话,然后一个字一个字的将其打印在屏幕上。那么我们需要一个char类型的变量 char1,两个线程,一个用于对char1赋值,一个用于读取char1的值。,我们设计如下代码来实现上述需求。
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Threading;
- namespace 线程同步interlocked
- {
- class Program
- {
- private static char result;
- private static string a = "青青子衿,悠悠我心!";
- static void Main(string[] args)
- {
- ThreadStart ts=write;
- ThreadStart ts2 = read;
- Thread readThread = new Thread(ts2);
- Thread writeThread = new Thread(ts);
- writeThread.Start();
- readThread.Start();
- }
-
- static void write()
- {
- for (int i = 0; i < a.Length; i++)
- {
- result = a[i];
- Thread.Sleep(20);
- }
- }
- static void read()
- {
- for (int i = 0; i < a.Length; i++)
- {
- char b = result;
- Console.Write(b);
- Thread.Sleep(20);
- }
- }
- }
- }
复制代码 这样写,貌似没有问题,但是当我们运行程序是就会发现,输出的文字乱七八糟,并不是我们所输入的原文。这是因为两个线程的执行几率并不是完全等分的,那么我们就需要这样来实现,当写入线程在写入的时候,就锁定这个变量,此时不允许读取线程来读取内容,等写完了这个字符,再解锁。同样的,读取线程也是一样。
interlocked类的部分方法
read() 读取计数器的值
Increment() 使计数器增加1
Decrement()使计数器减小1;
Add() 使计数器增加指定的值
Exchange() 把计数器设置为指定的值
CompareExchange() 先把计数器和某个值进行比较,若相等,就把计数器设为指定值
代码如下。- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Threading;
- namespace 线程同步interlocked
- {
- class Program
- {
- private static char result;
- private static string a = "青青子衿,悠悠我心!";
- static void Main(string[] args)
- {
- ThreadStart ts=write;
- ThreadStart ts2 = read;
- Thread readThread = new Thread(ts2);
- Thread writeThread = new Thread(ts);
- writeThread.Start();
- readThread.Start();
- }
- static long num = 0; //定义一个long变量用于计数,必须是long,因为interlocked的增加和减少计数器的方法的参数要求是long类型。
- static void write()
- {
- for (int i = 0; i < a.Length; i++)
- {
- while (Interlocked.Read(ref num) == 1) //这里必须使用引用来传递参数,当计数器为1时就不断的让他sleep
- { Thread.Sleep(10); }
- result = a[i];
- Interlocked.Increment(ref num);//写完后就让计数器增加1
-
- }
- }
- static void read()
- {
- for (int i = 0; i < a.Length; i++)
- {
- while (Interlocked.Read(ref num) == 0)
- { Thread.Sleep(10); }
- char b = result;
- Console.Write(b);
- Interlocked.Decrement(ref num);//读取完就让计数器减少1
- }
- }
- }
- }
复制代码 通过以上代码,我们就可以正常的输出字符串内容了。这里有一个问题,如果我不使用interlocked,而是直接操作num的值,也可以正常输出内容。那么是否这也是一种互锁呢,可是在我学习的资料中,并没有提到我的这种方法。是不是我这种写法并没有实现互锁,只是在这种特定情况下,输出内容正常罢了。知道的同学麻烦告知一下,这里先谢过了。代码是这样写的- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Threading;
- namespace 线程同步interlocked
- {
- class Program
- {
- private static char result;
- private static string a = "青青子衿,悠悠我心!";
- static void Main(string[] args)
- {
- ThreadStart ts=write;
- ThreadStart ts2 = read;
- Thread readThread = new Thread(ts2);
- Thread writeThread = new Thread(ts);
- writeThread.Start();
- readThread.Start();
- }
- static long num = 0;
- static void write()
- {
- for (int i = 0; i < a.Length; i++)
- {
- //while (Interlocked.Read(ref num) == 1)
- //{ Thread.Sleep(10); }
- while (num == 1)
- { Thread.Sleep(10); }
- result = a[i];
- //Interlocked.Increment(ref num);
- num += 1;
- }
- }
- static void read()
- {
- for (int i = 0; i < a.Length; i++)
- {
- //while (Interlocked.Read(ref num) == 0)
- //{ Thread.Sleep(10); }
- while (num == 0)
- { Thread.Sleep(10); }
- char b = result;
- Console.Write(b);
- num = num - 1;
- //Interlocked.Decrement(ref num);
- }
- }
- }
- }
复制代码 |