同步一直是多线程技术的关键。为了实现并发操作中的变量访问同步,可以采用局部锁、方法锁、线程锁、同步基元等方法。
这是一个为普通方法加入[MethodImpl(MethodImplOptions.Synchronized)]属性,使它成为同步方法的例子。
示例:直接用csc.exe编译即可。
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));
}
}
}
我的测试结果:
线程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类加入这些:
public static void SynchronizedMyMethod()
{
lock(syncObj)
{
Print('#', ++_syncI);
}
}