两个线程之间有同步也有异步执行,请高手帮我看看这样写对不对。
有两个线程A,B;A线程往表里面写数据,B线程交换数据,同时关闭当前表的触发器。注意:A,B操作的表都有触发器。
当A线程往TA表写数据时,TA表触发器往状态表写数据,这条数据是有效的。当B线程交换数据时,往TA或其他表写数时,TA触发器或其他表触发器也会往状态表写数据,但这条数据是无效的。所以,我的方法是,当B线程在交换数据前,先将要交换的表的触发器禁用,等交换完成后在启用触发器。这样会出现一个问题,如果线程A和B同时操作同一张表,当B线程先执行禁用触发器,数据还没有交换完成,触发器还没有被启用时,然后A线程往表里面写入数据,这时因为触发器关闭也就不会往状态表中写入数据了,所以这样操作是错误的;反过来,当A线程往同一张表写数据时,B线程是不应该禁用触发器的,这就是两个线程同步情况。但两个线程操作的不是同一张表,同步情况就不会存在了。所以,为什么说两个线程之间有同步也有异步。
所以,我模拟了以上的情况,写了一个Demo,请大家帮我看看,这样设计会不会出现问题。谢谢。(最好复制下来,调试)
/// <summary>
/// 两线程实现同步数据类
/// </summary>
public class ElementA
{
static string tableA = string.Empty;//A表名
static string tableB = null;//B表名
static bool signal = false;//是否需要同步
static CriticalRegion cr = new CriticalRegion();//临界区
/// <summary>
/// A表名
/// </summary>
public string TableA
{
set
{
tableA = value;
if (tableA == tableB)
signal = true;
else
signal = false;
}
}
/// <summary>
/// B表名
/// </summary>
public string TableB
{
set
{
tableB = value;
if (tableB == tableA)
signal = true;
else
signal = false;
}
}
/// <summary>
/// 是否需要同步,TRUE表示需要同步,FALSE表示不需要同步
/// </summary>
public bool Signal
{
get { return signal; }
}
/// <summary>
/// 临界区
/// </summary>
public CriticalRegion CriticalRegion
{
get { return cr; }
set { cr = value; }
}
//public Object LockObject
//{
// get { return lockobject; }
//}
}
/// <summary>
/// 临界区类
/// </summary>
public class CriticalRegion
{
bool criticalRegionControl = false;
/// <summary>
/// 临界区控制,TRUE表示有线程在执行;FALSE表示没有线程在执行,可以进入
/// </summary>
public bool CriticalRegionControl
{
get { return criticalRegionControl; }
set { criticalRegionControl = value; }
}
}
//////////////////////////////////////////
/// <summary>
/// 线程A会执行里面的方法
/// </summary>
public class RunA
{
public void Run(object da)
{
ElementA data = (ElementA)da;
string[] A = new string[] { "A", "B", "C", "A", "C", "A", "A", "C" };//模拟的数据表名
for (int i = 0; i < A.Length; i++)
{
data.TableA = A[i];//改表名
if (data.Signal)//判断两线程是否需要同步,TRUE表示需要同步,FALSE表示不需要同步
{
if (data.CriticalRegion.CriticalRegionControl == true)//判断临界区是否有线程,TRUE表示有线程在执行;FALSE表示没有线程执行,可以进入
{
while (data.CriticalRegion.CriticalRegionControl == false)//轮询等待另一个线程执行完成
{
Thread.Sleep(500);
}
lock (data.CriticalRegion)//互斥锁,当加锁时,另外的线程不能读data.N及修改
{
//int n = Convert.ToInt32(data.N) + 1;
data.CriticalRegion.CriticalRegionControl = true;
}
Option(A[i]);//执行表操作
data.CriticalRegion.CriticalRegionControl = false;//表示临界区为空,线程可以进入
data.TableA = string.Empty;
}
else
{
lock (data.CriticalRegion)//互斥锁,当加锁时,另外的线程不能读data.N及修改
{
//int n = Convert.ToInt32(data.N) + 1;
data.CriticalRegion.CriticalRegionControl = true;
}
Option(A[i]);//执行表操作
data.CriticalRegion.CriticalRegionControl = false;
data.TableA = string.Empty;//改表名
}
}
else
{
Option(A[i]);//执行操作
data.TableA = string.Empty;//改表名
}
//data.TableA = string.Empty;//改表名
}
}
private void Option(string tableA)
{
Console.WriteLine("A->" + tableA);
}
}
//////////////////////////////////////
/// <summary>
/// 线程B会执行里面的方法
/// </summary>
public class RunB
{
public void Run(object da)
{
ElementA data = (ElementA)da;
string[] B = new string[] { "A", "B", "C", "A", "C", "A", "A", "C" };
//string[] B = new string[] { "D", "A", "f", "c", "v", "er", "ac", "ee", "gb" };
for (int i = 0; i < B.Length; i++)
{
data.TableB = B[i];//改表名
if (data.Signal)//判断两线程是否需要同步,TRUE表示需要同步,FALSE表示不需要同步
{
if (data.CriticalRegion.CriticalRegionControl == true)//判断临界区是否有线程,TRUE表示有线程在执行;FALSE表示没有线程执行,可以进入
{
while (data.CriticalRegion.CriticalRegionControl == false)//轮询等待另一个线程执行完成
{
Thread.Sleep(500);//当临界区有线程在执行,轮询等待
}
lock (data.CriticalRegion)//互斥锁,当加锁时,另外的线程不能data.CriticalRegion及修改
{
data.CriticalRegion.CriticalRegionControl = true;
}
Option(B[i]);//执行表操作
data.CriticalRegion.CriticalRegionControl = false;
data.TableB = null;
}
else
{
lock (data.CriticalRegion)//互斥锁,当加锁时,另外的线程不能data.CriticalRegion修改
{
data.CriticalRegion.CriticalRegionControl = true;
}
Option(B[i]);//执行表操作
data.CriticalRegion.CriticalRegionControl = false;
data.TableB = null;
}
}
else
{
Option(B[i]);//执行表操作
data.TableB = null;
}
//data.TableB = null;//修改表名
}
}
private void Option(string tableB)
{
Console.WriteLine("B->" + tableB);
}
}
///////////////////////////////////////
namespace Test
{
class Program
{
static void Main(string[] args)
{
//Thread
ElementA el = new ElementA();
RunA a = new RunA();
RunB b = new RunB();
Thread ta = new Thread(new ParameterizedThreadStart(a.Run));
Thread tb = new Thread(new ParameterizedThreadStart(b.Run));
ta.Start(el);
tb.Start(el);
}
}
}
本来我开始考虑是,不管A,B线程,只要针对表操作,就把另外线程挂起,这样可以很方便,但效率很低,没有突出多线程的优点,所以,后来改成了上面的Demo的方式。
请高手多多指点。谢谢。