同步方法 [MethodImpl(MethodImplOptions.Synchronized)]

阅读更多

同步一直是多线程技术的关键。为了实现并发操作中的变量访问同步,可以采用局部锁、方法锁、线程锁、同步基元等方法。

这是一个为普通方法加入[MethodImpl(MethodImplOptions.Synchronized)]属性,使它成为同步方法的例子。

示例:直接用csc.exe编译即可。

/* * [MethodImpl(MethodImplOptions.Synchronized)]属性修饰同步方法 * 此例演示MyService的SynchronizedMyMethod方法是被修饰为同步调用, * 它影响的_syncI变量会每次调用方法时正确加1;而不会出现调用MyMethod方法, * 每次调用它的时候,不会等待上次调用的完成,导致竞争_i变量,_i读写的不准确。 * * 演示时,按一下回车键,观察输出*号图形中,是否正确递增输出。 * 输出*号完成后,再按一下回车键,观察输出#号图形中,是否正确递增输出。 * 输出#号完成后,可以再按一下回车键,观察下一次的*号输出,依此类推。 * * 观察结果:*号的输出越来越不稳定,而#号的输出永远都是递增输出。 * 其中*号输出调用的MyMethod方法,#号输出调用的是SynchronizedMyMethod方法。 */ using System; using System.Runtime.CompilerServices; using System.Threading; namespace ConsoleApplication1 { internal class Program { private const int Max = MyService.Max; private static void Main() { Console.WriteLine("同步方法测试|oyi319|按Enter键继续|按Ctrl+C退出"); Console.ReadLine(); for (int s = 0;; s = s > 0 ? 0 : 1) { for (int i = 0; i < Max; i++) ThreadPool.QueueUserWorkItem(TestTask, s); Console.ReadLine(); } } private static void TestTask(object stateInfo) { if ((int) stateInfo == 0) MyService.MyMethod(); else MyService.SynchronizedMyMethod(); } } internal class MyService { public const int Max = 50; private static int _i; private static int _syncI; private static readonly Random R = new Random(); public static void MyMethod() { Print('*', ++_i); } [MethodImpl(MethodImplOptions.Synchronized)] public static void SynchronizedMyMethod() { Print('#', ++_syncI); } private static void Print(char ch, int i) { Console.WriteLine("线程Id= " + Thread.CurrentThread.GetHashCode() + "\t " + new string(ch, i%Max)); Thread.Sleep(R.Next(0, 500)); } } }

我的测试结果:

同步方法测试|oyi319|按Enter键继续|按Ctrl+C退出 线程Id= 7 * 线程Id= 11 ** 线程Id= 7 *** 线程Id= 11 **** 线程Id= 7 ***** 线程Id= 11 ****** 线程Id= 11 ******* 线程Id= 11 ******** 线程Id= 7 ********* 线程Id= 12 ********** 线程Id= 7 *********** 线程Id= 12 ************ 线程Id= 11 ************* 线程Id= 12 ************** 线程Id= 13 *************** 线程Id= 12 ***************** 线程Id= 7 **************** 线程Id= 11 ****************** 线程Id= 12 ******************* 线程Id= 13 ******************** 线程Id= 13 ********************* 线程Id= 11 ********************** 线程Id= 7 *********************** 线程Id= 14 ************************ 线程Id= 14 ************************* 线程Id= 11 ************************** 线程Id= 7 *************************** 线程Id= 12 **************************** 线程Id= 13 ***************************** 线程Id= 12 ****************************** 线程Id= 11 ******************************* 线程Id= 11 ******************************** 线程Id= 12 ******************************** 线程Id= 14 ********************************* 线程Id= 15 ********************************** 线程Id= 15 *********************************** 线程Id= 7 ************************************ 线程Id= 12 ************************************* 线程Id= 12 ************************************** 线程Id= 12 *************************************** 线程Id= 13 **************************************** 线程Id= 14 ***************************************** 线程Id= 11 ****************************************** 线程Id= 7 ******************************************* 线程Id= 15 ******************************************** 线程Id= 11 ********************************************* 线程Id= 16 ********************************************** 线程Id= 12 *********************************************** 线程Id= 13 ************************************************ 线程Id= 11 ************************************************* 线程Id= 15 # 线程Id= 7 ## 线程Id= 11 ### 线程Id= 7 #### 线程Id= 12 ##### 线程Id= 14 ###### 线程Id= 13 ####### 线程Id= 16 ######## 线程Id= 15 ######### 线程Id= 17 ########## 线程Id= 18 ########### 线程Id= 11 ############ 线程Id= 7 ############# 线程Id= 12 ############## 线程Id= 14 ############### 线程Id= 13 ################ 线程Id= 16 ################# 线程Id= 15 ################## 线程Id= 17 ################### 线程Id= 18 #################### 线程Id= 11 ##################### 线程Id= 7 ###################### 线程Id= 12 ####################### 线程Id= 14 ######################## 线程Id= 13 ######################### 线程Id= 16 ########################## 线程Id= 15 ########################### 线程Id= 17 ############################ 线程Id= 18 ############################# 线程Id= 11 ############################## 线程Id= 7 ############################### 线程Id= 12 ################################ 线程Id= 14 ################################# 线程Id= 13 ################################## 线程Id= 16 ################################### 线程Id= 15 #################################### 线程Id= 17 ##################################### 线程Id= 18 ###################################### 线程Id= 11 ####################################### 线程Id= 7 ######################################## 线程Id= 12 ######################################### 线程Id= 14 ########################################## 线程Id= 13 ########################################### 线程Id= 16 ############################################ 线程Id= 15 ############################################# 线程Id= 17 ############################################## 线程Id= 18 ############################################### 线程Id= 11 ################################################ 线程Id= 7 ################################################# 线程Id= 12

上面的测试结果中,第18行,第35行等,输出的*号图形个数产生了问题,而#号输出是正确的。

示例代码变成同步锁的方式,相当于在MyService类加入一个同步锁对象syncObj,然后在SynchronizedMyMethod的语句中加入lock块,对MyService类加入这些:

private static object syncObj = new object(); public static void SynchronizedMyMethod() { lock(syncObj) { Print('#', ++_syncI); } }

你可能感兴趣的:(多线程,thread)