在线程应用程序中,线程需要相互共享数据。但是,应用程序应该确保一个线程不更改另一个线程使用的数据。考虑有两个线程的场景。一个线程从文件读取工资,另一个线程尝试更新工资。当两个线程同时工作时,数据就会受损。下图显示了两个线程同时访问一个文件的数据。
线程的同步确保如果两个或多个线程需要访问共享资源,那么那个资源一次仅被一个线程使用。您可以使用synchroized关键字同步代码。可以在任何给定的时间仅调用一个同步方法。
同步基于监视的概念。监视器时一个对象, 用于数据成员的锁以及类的方法。所有对象和类都与监视器关联,并且在指定时间只有一个线程能够拥有监视器。要进入一个对象的监视器,需要调用synchroized关键字修改的方法。
监视器控制同步方法访问一个对象或类的方法。当线程获取锁时,就是说它进入了监视器。监视器确保在任何给定的时间仅一个线程访问资源。
当线程在同步方法内的时候,所有试图在同一个实例上调用方法的其他线程必须等待。在同步方法执行的期间,对象时被锁定的以便没有其他的同步方法被调用。当方法完成其执行时会自动释放监视器。监视器也在同步方法执行Wait()方法的时候被释放。下图显示了线程同步的一个示例。
在上图中,Thread1正在更新文件中Stella的工资时,在Salary.xls文件上有一个锁。Thread2要从Salary.xls文件读取Stella的工资,它正在等待Thread1释放文件上的锁。
当线程调用Wait()方法时,它暂时释放它拥有的锁。而且,线程停止运行,而且被加入到那个对象的等待线程列表中。
下图显示了线程间的同步。
使用监视锁锁定代码
System.Monitor类能够以锁和信号的方式使代码块的访问序列化。例如,您有一个将内容写到文件的方法。此方法不应由两个或多个线程同时使用来讲内容写到文件。您可以使用Monitor类来锁定方法,以便在给定时间仅有一个线程能执行它。
考虑同步的示例。有两个进程,两个进程都将调用WriteData()方法。您可以使用以下方式锁定WriteData()方法:
使用监视锁及Monitor.Enter()方法
Monitor类的Enter()方法尝试获取对象上的监视锁。如果另一个线程已经有锁,会阻止方法直到锁被释放。然后调用Monitor.Exit()方法来释放此锁。
以下代码使用Monitor.Enter()方法锁定WriteData()方法:
using System;
using System.Threading;
namespace ThreadExample
{
class FileAccess
{
public void WriteData(string Data)
{
Monitor.Enter(this);
Console.WriteLine("FileAccess.WriteData - Started");
Console.WriteLine("FileAccess.WriteData - Working");
for ( int Cnt = 0; Cnt