C# 中多线程锁的使用经验:全局锁,实例锁
全局锁
private static object _exeLock = new object();
static 静态的是全应用程序的资源。如果在一个类里定义了这样一个锁,你在调用使用这个类的时候,是NEW了一个对象,并把这个对象给了一个静态全局变量中保存。这时这个锁就是全局锁了。
你在调用带锁的方法时会受到【全局锁】的影响。
实例锁
private object _exeLock = new object();
影响只在这个对象实例中。
示例
全局锁代码
类的代码
/// <summary>
/// 雷赛板卡 AxisDMC3000
/// </summary>
public class DMC3000 : AxisModel
{
public DMC3000() { }
public DMC3000(string name) { }
/// <summary>
/// 全局锁
/// </summary>
private static object _exeLockAll = new object();
/// <summary>
/// 对象锁
/// </summary>
//private object _exeLock = new object();
/// <summary>
/// 移动到指定位置
/// </summary>
/// <param name="posname">位置名称</param>
/// <returns></returns>
public override bool MoveAbs(string posname)
{
var isFinsh = false;
lock (_exeLockAll)
{
try
{
int dis = (int)(GetAxisPosList(posname) * Param.PulseRatio);
SetAxisParam();
//单轴运动函数
//Dist 目标位置,单位:pulse,范围:-134217728~+134217728
//posi_mode 运动模式,0:相对坐标模式,1:绝对坐标模式
isFinsh = LTDMC.dmc_pmove(CardNum, AxisNum, dis, 1) == 0;
}
catch (Exception ex)
{
isFinsh = false;
WorkFlow.ShowMsgError("MoveAbs(string posname) 异常:" + ex.Message,
"MoveAbs(string posname)");
}
}
return isFinsh;
}
}
上面的代码中有一个【全局锁】和一个用了【全局锁】的方法
调用这个类时的代码
创建两个类对象
#region 轴
/// <summary>
/// (焊接)X轴 左右移动X轴
/// </summary>
private static DMC3000 _axis_CarryX;
/// <summary>
/// (焊接)Y轴 前后移动Y轴
/// </summary>
private static DMC3000 _axis_CarryY;//Axis_CarryY = 1,
/// <summary>
/// 送针X 左右移动
/// </summary>
private static DMC3000 _axis_SongzhengX;
#endregion
/// <summary>
/// 初始化 轴
/// </summary>
/// <returns></returns>
public static bool InitAxis()
{
var isFinish = false;
_axis_CarryX = new DMC3000(AxisType.Axis_CarryX.ToString());
_axis_CarryY = new DMC3000(AxisType.Axis_CarryY.ToString());
_axis_SongzhengX = new DMC3000(AxisType.Axis_SongzhengX.ToString());
return isFinish;
}
上面三个轴都是new的方式生成是三个独立的对象。
但在用线程Task调用MoveAbs方法时你会发现,三个轴的运动情况是一个一个的移动。而不是同时移动的
public static void Test()
{
Task.Factory.StartNew(() => {
_axis_CarryX.MoveAbs("ToPos");
});
Task.Factory.StartNew(() => {
_axis_CarryY.MoveAbs("ToPos");
});
Task.Factory.StartNew(() => {
_axis_SongzhengX.MoveAbs("ToPos");
});
}
原因就是对象里使用对【全局锁】每个对象在调用MoveAbs方法时都会进行排对,第一个线程用完后,第二个线程去用。以此类推。这像就相对于是单线程了,上面开了三个线程去执行,完全没有用和不用Task调用是一样的。这样的效果一定不是我们所希望的。那要怎么解决这个问题呢。
有人可能会说那就不用锁了。这样不是解决问题了吗?这也是一种解决方法。但我在工作中。发现一个问题就是在不用锁时发现有时轴无法走到指定的点位。在获取轴当前的坐标时也不是我们指定的坐标位。本文就是为解决这个时而出现的多线程问题而写的总结。
为了达到同步效果又要解决一个轴在多个线程中有调用的情况时。我选择了【对象锁】解决问题。【对象锁】从名称中就可以知道,这锁的范围在对象中,不会影响到其他对象的的调用。这样就可以解决问题。多线程中同时调用MoveAbs方法时进行锁排对,执行和取读当前坐标不会因为多线程为影响。文章来源:https://www.toymoban.com/news/detail-839633.html
实例锁代码
/// <summary>
/// 雷赛板卡 AxisDMC3000
/// </summary>
public class DMC3000 : AxisModel
{
public DMC3000() { }
public DMC3000(string name) { }
/// <summary>
/// 对象锁
/// </summary>
private object _exeLock = new object();
/// <summary>
/// 移动到指定位置
/// </summary>
/// <param name="posname">位置名称</param>
/// <returns></returns>
public override bool MoveAbs(string posname)
{
var isFinsh = false;
lock (_exeLock)
{
try
{
int dis = (int)(GetAxisPosList(posname) * Param.PulseRatio);
SetAxisParam();
//单轴运动函数
//Dist 目标位置,单位:pulse,范围:-134217728~+134217728
//posi_mode 运动模式,0:相对坐标模式,1:绝对坐标模式
isFinsh = LTDMC.dmc_pmove(CardNum, AxisNum, dis, 1) == 0;
}
catch (Exception ex)
{
isFinsh = false;
WorkFlow.ShowMsgError("MoveAbs(string posname) 异常:" + ex.Message,
"MoveAbs(string posname)");
}
}
return isFinsh;
}
}
代码差别不大就中对像锁中没有使用static关键字。文章来源地址https://www.toymoban.com/news/detail-839633.html
到了这里,关于C# 中多线程锁的使用经验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!