lock锁住编号就行,不要锁住同一个变量
不可以的,lock不可以锁值类型,锁字符串的话也是没有效果的,因为字符串有驻留机制;new一个包含用户编号的实体也是不行的,因为每次请求都是新的实体,跟之前的已经不是同一个实体了;我在想是不是解决方法的方向错了。。。
@阿祖哥: 可以的,你试试就知道了
string NO="1"
lock(NO)
{}
这样就可以的,你可以加延时测试下就可以了
@jqw2009: 你看,我试过了的,这样的话,其实锁是没有作用的,同一用户的线程并不是同步,我希望的是 这个43的用户线程同步
@阿祖哥: 有个关键的东西你要加上去,明天再告诉你
@jqw2009: 大哥,别这样好吗?有方案的话就尽快告诉我吧。。。
不同用户使用不同线程来处理呢?
就是不同线程的
我fuck了半天,看结果是可以的,没毛病,你再多加点数据fuck一下看看
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace LockTest
{
class Program
{
static void Main(string[] args)
{
FuckMe fuckMe = new FuckMe();
List<Person> peopleSet1 = new List<Person>();
List<Person> peopleSet2 = new List<Person>();
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 3; j++)
{
peopleSet1.Add(new Person { Id = i.ToString() ,Name = $"{i}-{j}" });
peopleSet2.Add(new Person { Id = i.ToString(), Name = $"{i}-{j}" });
}
}
Thread t1 = new Thread(() =>
{
foreach (var item in peopleSet1)
{
fuckMe.Fuck(item);
}
});
Thread t2 = new Thread(() =>
{
foreach (var item in peopleSet2)
{
fuckMe.Fuck(item);
}
});
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.ReadLine();
}
}
class Person
{
public string Id { get; set; }
public string Name { get; internal set; }
}
class FuckMe
{
private string[] _lockObjects = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
public void Fuck(Person person)
{
string lockObj = _lockObjects.First(l => l == person.Id);
lock (lockObj)
{
Console.WriteLine($"begin fuck Id:{person.Id}, name:{person.Name}");
Thread.Sleep(500);
Console.WriteLine($"end fuck Id: {person.Id}, name:{person.Name}");
}
}
}
}
_lockObjects 可以动态构建,我举例子写死了
先感谢你哈,我这边试下尝尝咸淡先
你好,用你这种方式是可以的,但是有个问题我没搞懂,为什么我直接lock("43")不可以,用你这种方式就可以了呢?
还有个问题,我这个用户编号是不确定的,我不能把库里所有用户编号放在一个数组里,那只能在主方法里用list把当前编号加到队列里,再去过滤使用,总觉得怪怪的,请问有什么好方法么?
@阿祖哥: 可能内容相同的字符串实际上是两个不同的对象吧
@阿祖哥: 没想到别的方法,虽然不好,胜过没有吧。不知道用户的规模多大啊
@阿祖哥: 或者这样也行啊,你把当前正在进行的用户的编号存起来,每次有用户来执行,你就看看这个用户的编号是否已经存在了,没有则执行,有就return了,把判断的代码放了lock里。不知道你们具体的业务是什么样的,把所有的用户放了队列,判断出队的用户可以执行不,可以的话就执行,不可以的话再如队
@会长: 目前好像也只能这样了,业务主要是为了解决用户领取优惠券的时候,要检查是否已经领过优惠券,这个逻辑比较耗时,连续多次调用接口的话,会导致校验失败,所以相同用户领取的时候需要线程同步,但是不影响其他用户领取优惠券。
用户量有100万左右,我现在打算过1分钟就清空list(因为同个用户连续多次调用接口不会超过1分钟),这样应该没问题
@阿祖哥: 个人认为,这个方案不是很好,从运行结果上是OK
但是百万级别的数据,如果是发生高并发,算上用户的重复操作,那么瞬建最大并发容量至少需要达到1万以上,在面临高并发的时候,性能开销堪忧;
优先你需要考虑你的list的线程安全,多个线程同时读写一个不锁的list,那么如果两个同样的id同时去list里查询,那么都会返回无数据。庞大的list给内存和GC带来的负担外,每次在庞大的list中进行字符串匹配也会成为性能上的障碍。
最重要的是你如何保证每个ID在list中的生存周期独立,这个很重要,例如id=100第一次进来,被压入list,此时你的公共的1分钟到,清空list,马上第二次id=100的请求又进来。产生错误的并发数据。
来一个字典,把编号做为Key,new Object()作为Value,lock的是value就好了,别使用string为作lock对象。
来,我给楼主一个思路。
设置10个static object锁,并行10个线程,每个线程都锁一个不同的锁,这样请求进来会排成10个队列,既能同时处理10个请求,又能锁住你想要锁的那一类请求。
我也遇到了同样的问题,使用Mutex可以很简单的解决这个问题,并发的时候,相同用户id的线程就会排队执行