设为首页 收藏本站
查看: 1473|回复: 0

重新想象 Windows 8 Store Apps (46)

[复制链接]

尚未签到

发表于 2015-5-22 08:10:40 | 显示全部楼层 |阅读模式
  [源码下载]




重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock  
作者:webabcd

介绍
重新想象 Windows 8 Store Apps 之 线程同步


  • lock - 其实就是对 Monitor.Enter() 和 Monitor.Exit() 的一个封装
  • Monitor - 锁
  • Interlocked - 为多个线程共享的数字型变量提供原子操作
  • Mutex - 互斥锁,主要用于同一系统内跨进程的互斥锁
  • ReaderWriterLock - 读写锁
  
示例
1、演示 lock 的使用
Thread/Lock/LockDemo.xaml











  Thread/Lock/LockDemo.xaml.cs



/*
* 演示 lock 的使用
*
* 注:lock 其实就是对 Monitor.Enter() 和 Monitor.Exit() 的一个封装
*/
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace XamlDemo.Thread.Lock
{
public sealed partial class LockDemo : Page
{
// 需要被 lock 的对象
private static readonly object _objLock = new object();
private static int _countWithoutLock;
private static int _countWithLock;
public LockDemo()
{
this.InitializeComponent();
}
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
List tasks = new List();
// 一共 100 个任务并行执行,每个任务均累加同一个静态变量 100000 次,以模拟并发访问静态变量的场景
for (int i = 0; i < 100; i++)
{
Task task = Task.Run(
() =>
{
/******************有锁的逻辑开始******************/
try
{
// 通过 lock 锁住指定的对象以取得排它锁,在 lock 区域内的代码执行完毕后释放排它锁,排它锁释放之前其它进入到此的线程会排队等候
lock (_objLock)
{
for (int j = 0; j < 100000; j++)
{
_countWithLock++;
}
}
}
finally { }
/******************有锁的逻辑结束******************/

/******************没锁的逻辑开始******************/
for (int j = 0; j < 100000; j++)
{
_countWithoutLock++;
}
/******************没锁的逻辑结束******************/
});
tasks.Add(task);
}
// 等待所有任务执行完毕
await Task.WhenAll(tasks);
lblMsgWithoutLock.Text = "计数器(不带锁)结果:" + _countWithoutLock.ToString();
lblMsgWithLock.Text = "计数器(带锁)结果:" + _countWithLock.ToString();
}
}
}
  
2、演示 Monitor 的使用
Thread/Lock/MonitorDemo.xaml










  Thread/Lock/MonitorDemo.xaml.cs



/*
* 演示 Monitor 的使用
*
* 本例说明:
* 由于 Task 基于线程池,所以 task1 和 task2 的启动顺序是不一定的,以下步骤假定 task1 先执行,task2 后执行
* 1、task1 取得排它锁
* 2、task1 Monitor.Wait() - 释放排它锁,然后 task1 进入等待队列,可以为其指定一个超时时间,超过则进入就绪队列
* 3、task2 取得排它锁
* 4、task2 Monitor.Pulse() - 让等待队列中的一个线程进入就绪队列(Monitor.PulseAll() 的作用是将等待队列中的全部线程全部放入就绪队列)
* 5、task1 进入就绪队列
* 6、task2 Monitor.Wait() - 释放排它锁,然后 task2 进入等待队列
* 7、task1 取得排它锁
* 8、以上步骤不断往复
*
* 注:
* 1、Wait() 和 Pulse() 必须在 Enter() 和 Exit() 之间,或者在 lock(){ } 中
* 2、只有就绪队列中的线程才能取得排它锁,等待队列中的线程是无法取得排它锁的
*/
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace XamlDemo.Thread.Lock
{
public sealed partial class MonitorDemo : Page
{
// 需要被 lock 的对象
private static readonly object _objLock = new object();
public MonitorDemo()
{
this.InitializeComponent();
}
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
string result = "";
// 在 task1 中执行则为 true,在 task2 中执行则为 false
bool flag = true;
Task task1 = Task.Run(
() =>
{
try
{
// 在指定的对象上取得排它锁
                        Monitor.Enter(_objLock);
for (int i = 0; i < 10; i++)
{
if (flag)
Monitor.Wait(_objLock);
flag = true;
result += string.Format("task1 i:{0}, taskId:{1}", i, Task.CurrentId);
result += Environment.NewLine;
Monitor.Pulse(_objLock);
}
}
finally
{
// 在指定的对象上释放排它锁
                        Monitor.Exit(_objLock);
}
});
Task task2 = Task.Run(
() =>
{
try
{
// 在指定的对象上取得排它锁
                        Monitor.Enter(_objLock);
for (int i = 0; i < 10; i++)
{
if (!flag)
Monitor.Wait(_objLock);
flag = false;
result += string.Format("task2 i:{0}, taskId:{1}", i, Task.CurrentId);
result += Environment.NewLine;
Monitor.Pulse(_objLock);
}
}
finally
{
// 在指定的对象上释放排它锁
                        Monitor.Exit(_objLock);
}
});
await Task.WhenAll(task1, task2);
lblMsg.Text = result;
}
}
}
  
3、演示 Interlocked 的使用
Thread/Lock/InterlockedDemo.xaml











  Thread/Lock/InterlockedDemo.xaml.cs



/*
* 演示 Interlocked 的使用
*
* Interlocked - 为多个线程共享的数字型变量提供原子操作,其提供了各种原子级的操作方法,如:增减变量、比较变量、指定变量的值
*
* 注:
* long Read(ref long location) - 用于在 32 位系统上以原子方式读取 64 位值(32 位系统访问 32 位值本身就是原子的,64 位系统访问 64 位值本身就是原子的)
*/
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace XamlDemo.Thread.Lock
{
public sealed partial class InterlockedDemo : Page
{
private static int _countWithoutLock;
private static int _countWithLock;
public InterlockedDemo()
{
this.InitializeComponent();
}
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
List tasks = new List();
// 一共 100 个任务并行执行,每个任务均累加同一个静态变量 100000 次,以模拟并发访问静态变量的场景
for (int i = 0; i < 100; i++)
{
Task task = Task.Run(
() =>
{
/******************有锁的逻辑开始******************/
for (int j = 0; j < 100000; j++)
{
// 原子方式让 _countWithLock 加 1
Interlocked.Increment(ref _countWithLock);
}
/******************有锁的逻辑结束******************/

/******************没锁的逻辑开始******************/
for (int j = 0; j < 100000; j++)
{
_countWithoutLock++;
}
/******************没锁的逻辑结束******************/
});
tasks.Add(task);
}
await Task.WhenAll(tasks);
lblMsgWithoutLock.Text = "计数器(不带锁)结果:" + _countWithoutLock.ToString();
lblMsgWithLock.Text = "计数器(带锁)结果:" + _countWithLock.ToString();
}
}
}
  
4、演示 Mutex 的使用
Thread/Lock/MutexDemo.xaml











  Thread/Lock/MutexDemo.xaml.cs



/*
* 演示 Mutex 的使用
*
* Mutex - 互斥锁,主要用于同一系统内跨进程的互斥锁
*/
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace XamlDemo.Thread.Lock
{
public sealed partial class MutexDemo : Page
{
private Mutex _mutex = new Mutex();
private static int _countWithoutLock;
private static int _countWithLock;
public MutexDemo()
{
this.InitializeComponent();
}
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
List tasks = new List();
// 一共 100 个任务并行执行,每个任务均累加同一个静态变量 100000 次,以模拟并发访问静态变量的场景
for (int i = 0; i < 100; i++)
{
Task task = Task.Run(
() =>
{
/******************有锁的逻辑开始******************/
// 当前线程拿到 Mutex,阻塞当前线程,可以指定阻塞的超时时间
                        _mutex.WaitOne();
for (int j = 0; j < 100000; j++)
{
_countWithLock++;
}
// 释放 Mutex
                        _mutex.ReleaseMutex();
/******************有锁的逻辑结束******************/

/******************没锁的逻辑开始******************/
for (int j = 0; j < 100000; j++)
{
_countWithoutLock++;
}
/******************没锁的逻辑结束******************/
});
tasks.Add(task);
}
await Task.WhenAll(tasks);
lblMsgWithoutLock.Text = "计数器(不带锁)结果:" + _countWithoutLock.ToString();
lblMsgWithLock.Text = "计数器(带锁)结果:" + _countWithLock.ToString();
}
}
}
  
5、演示 ReaderWriterLockSlim 的使用
Thread/Lock/ReaderWriterLockDemo.xaml











  Thread/Lock/ReaderWriterLockDemo.xaml.cs



/*
* 演示 ReaderWriterLockSlim 的使用
*
* ReaderWriterLock - 读写锁(WinRT 中不提供)
* ReaderWriterLockSlim - 轻量级的 ReaderWriterLock
*     支持进入/离开读锁,进入/离开写锁,读锁升级为写锁
*     支持相关状态的获取,如:当前线程是否进入了读锁以及进入读锁的次数,是否进入了写锁以及进入写锁的次数,是否由读锁升级为了写锁以及由读锁升级为写锁的次数
*
* 注:
* 1、每次可以有多个线程进入读锁
* 2、每次只能有一个线程进入写锁
* 3、进入写锁后,无法进入读锁
*
*
* 本例模拟了一个“高频率读,低频率写”的场景
*/
using System;
using System.Threading;
using Windows.System.Threading;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace XamlDemo.Thread.Lock
{
public sealed partial class ReaderWriterLockDemo : Page
{
ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
public ReaderWriterLockDemo()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ThreadPoolTimer.CreatePeriodicTimer(
(timer) =>
{
// 进入读锁
                    _rwLock.EnterReadLock();
OutMsgForRead("读:" + DateTime.Now.ToString("mm:ss.fff"));
// 离开读锁
                    _rwLock.ExitReadLock();
},
TimeSpan.FromMilliseconds(100));

ThreadPoolTimer.CreatePeriodicTimer(
(timer) =>
{
// 进入写锁
                   _rwLock.EnterWriteLock();
new ManualResetEvent(false).WaitOne(3000); // 本线程停 3000 毫秒
OutMsgForWrite("写:" + DateTime.Now.ToString("mm:ss.fff"));
// 离开写锁
                   _rwLock.ExitWriteLock();
},
TimeSpan.FromMilliseconds(5000));
}
private async void OutMsgForRead(string msg)
{
await Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.High,
() =>
{
lblMsgForRead.Text = msg;
});
}
private async void OutMsgForWrite(string msg)
{
await Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.High,
() =>
{
lblMsgForWrite.Text = msg;
});
}
}
}
  
OK
[源码下载]

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-69341-1-1.html 上篇帖子: 重新想象 Windows 8 Store Apps (47) 下篇帖子: 重新想象 Windows 8 Store Apps (45)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表