先前也知道,Monitor实现的是在读写两种情况的临界区中只可以让一个线程访问,那么如果业务中存在”读取密集型“操作,就
好比数据库一样,读取的操作永远比写入的操作多。针对这种情况,我们使用Monitor的话很吃亏,不过没关系,ReadWriterLock
就很牛X,因为实现了”写入串行“,”读取并行“。
ReaderWriteLock中主要用3组方法:
<1> AcquireWriterLock: 获取写入锁。
ReleaseWriterLock:释放写入锁。
<2> AcquireReaderLock: 获取读锁。
ReleaseReaderLock:释放读锁。
<3> UpgradeToWriterLock:将读锁转为写锁。
DowngradeFromWriterLock:将写锁还原为读锁。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication3 { class Program { static List<int> list = new List<int>(); static ReaderWriterLock rw = new System.Threading.ReaderWriterLock(); static void Main(string[] args) { Thread t1 = new Thread(AutoAddFunc); Thread t2 = new Thread(AutoReadFunc); t1.Start(); t2.Start(); Console.Read(); } public static void AutoAddFunc() { //3000ms插入一次 Timer timer1 = new Timer(new TimerCallback(Add), null, 0, 3000); } public static void AutoReadFunc() { //1000ms自动读取一次 Timer timer1 = new Timer(new TimerCallback(Read), null, 0, 1000); Timer timer2 = new Timer(new TimerCallback(Read), null, 0, 1000); Timer timer3 = new Timer(new TimerCallback(Read), null, 0, 1000); } public static void Add(object obj) { var num = new Random().Next(0, 1000); //写锁 rw.AcquireWriterLock(TimeSpan.FromSeconds(30)); list.Add(num); Console.WriteLine("我是线程{0},我插入的数据是{1}。", Thread.CurrentThread.ManagedThreadId, num); //释放锁 rw.ReleaseWriterLock(); } public static void Read(object obj) { //读锁 rw.AcquireReaderLock(TimeSpan.FromSeconds(30)); Console.WriteLine("我是线程{0},我读取的集合为:{1}", Thread.CurrentThread.ManagedThreadId, string.Join(",", list)); //释放锁 rw.ReleaseReaderLock(); } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using System.Timers; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public List<int> list = new List<int>(); public ReaderWriterLock rw = new ReaderWriterLock(); private void button1_Click(object sender, EventArgs e) { //读取 Thread t1 = new Thread(add); Thread t2 = new Thread(read); t1.Start(); t2.Start(); timer1.Enabled = true; timer2.Enabled = true; } public void add(object obj) { //var num = new Random().Next(0, 1000); Thread.Sleep(30); Random r = new Random(); List<int> l = new List<int>(); for (int j = 0; j < 6; j++) { int lable = r.Next(1, 34); if (l.Contains(lable)) { j--; } else { l.Add(lable); } } l.Sort(); int lan = r.Next(1, 17); string zu = l[0].ToString() + " " + l[1].ToString() + " " + l[2].ToString() + " " + l[3].ToString() + " " + l[4].ToString() + " " + l[5].ToString() + "-" + lan; //写锁 rw.AcquireWriterLock(TimeSpan.FromSeconds(30)); listBox1.Items.Add(zu); //释放锁 rw.ReleaseWriterLock(); } public void read(object obj) { rw.AcquireReaderLock(TimeSpan.FromSeconds(30)); for (int i = 0; i < listBox1.Items.Count; i++) { textBox1.Text = string.Join(",", listBox1.Items[i].ToString()); } //释放锁 rw.ReleaseReaderLock(); } private void timer2_Tick(object sender, EventArgs e) { read(null); read(null); read(null); } private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; } private void timer1_Tick(object sender, EventArgs e) { add(null); } } }