[源碼下載]
html
做者:webabcd
介紹
從新想象 Windows 8 Store Apps 之 線程同步html5
示例
一、演示 lock 的使用
Thread/Lock/LockDemo.xamlweb
<Page x:Class="XamlDemo.Thread.Lock.LockDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Lock" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsgWithoutLock" FontSize="14.667" /> <TextBlock Name="lblMsgWithLock" FontSize="14.667" /> </StackPanel> </Grid> </Page>
Thread/Lock/LockDemo.xaml.csexpress
/* * 演示 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<Task> tasks = new List<Task>(); // 一共 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(); } } }
二、演示 Monitor 的使用
Thread/Lock/MonitorDemo.xamlwindows
<Page x:Class="XamlDemo.Thread.Lock.MonitorDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Lock" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsg" FontSize="14.667" /> </StackPanel> </Grid> </Page>
Thread/Lock/MonitorDemo.xaml.cs多線程
/* * 演示 Monitor 的使用 * * 本例說明: * 因爲 Task 基於線程池,因此 task1 和 task2 的啓動順序是不必定的,如下步驟假定 task1 先執行,task2 後執行 * 一、task1 取得排它鎖 * 二、task1 Monitor.Wait() - 釋放排它鎖,而後 task1 進入等待隊列,能夠爲其指定一個超時時間,超過則進入就緒隊列 * 三、task2 取得排它鎖 * 四、task2 Monitor.Pulse() - 讓等待隊列中的一個線程進入就緒隊列(Monitor.PulseAll() 的做用是將等待隊列中的所有線程所有放入就緒隊列) * 五、task1 進入就緒隊列 * 六、task2 Monitor.Wait() - 釋放排它鎖,而後 task2 進入等待隊列 * 七、task1 取得排它鎖 * 八、以上步驟不斷往復 * * 注: * 一、Wait() 和 Pulse() 必須在 Enter() 和 Exit() 之間,或者在 lock(){ } 中 * 二、只有就緒隊列中的線程才能取得排它鎖,等待隊列中的線程是沒法取得排它鎖的 */ 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; } } }
三、演示 Interlocked 的使用
Thread/Lock/InterlockedDemo.xaml併發
<Page x:Class="XamlDemo.Thread.Lock.InterlockedDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Lock" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsgWithoutLock" FontSize="14.667" /> <TextBlock Name="lblMsgWithLock" FontSize="14.667" /> </StackPanel> </Grid> </Page>
Thread/Lock/InterlockedDemo.xaml.csapp
/* * 演示 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<Task> tasks = new List<Task>(); // 一共 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(); } } }
四、演示 Mutex 的使用
Thread/Lock/MutexDemo.xamlasp.net
<Page x:Class="XamlDemo.Thread.Lock.MutexDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Lock" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsgWithoutLock" FontSize="14.667" /> <TextBlock Name="lblMsgWithLock" FontSize="14.667" /> </StackPanel> </Grid> </Page>
Thread/Lock/MutexDemo.xaml.csasync
/* * 演示 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<Task> tasks = new List<Task>(); // 一共 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(); } } }
五、演示 ReaderWriterLockSlim 的使用
Thread/Lock/ReaderWriterLockDemo.xaml
<Page x:Class="XamlDemo.Thread.Lock.ReaderWriterLockDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Lock" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsgForRead" FontSize="14.667" /> <TextBlock Name="lblMsgForWrite" FontSize="14.667" /> </StackPanel> </Grid> </Page>
Thread/Lock/ReaderWriterLockDemo.xaml.cs
/* * 演示 ReaderWriterLockSlim 的使用 * * ReaderWriterLock - 讀寫鎖(WinRT 中不提供) * ReaderWriterLockSlim - 輕量級的 ReaderWriterLock * 支持進入/離開讀鎖,進入/離開寫鎖,讀鎖升級爲寫鎖 * 支持相關狀態的獲取,如:當前線程是否進入了讀鎖以及進入讀鎖的次數,是否進入了寫鎖以及進入寫鎖的次數,是否由讀鎖升級爲了寫鎖以及由讀鎖升級爲寫鎖的次數 * * 注: * 一、每次能夠有多個線程進入讀鎖 * 二、每次只能有一個線程進入寫鎖 * 三、進入寫鎖後,沒法進入讀鎖 * * * 本例模擬了一個「高頻率讀,低頻率寫」的場景 */ 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
[源碼下載]