我不熟悉Java中的多线程,也不太了解发生了什么.
从在线教程和讲义中,我知道synchronized必须应用于非null对象的块确保只有一个线程可以执行该代码块.由于数组是Java中的对象,因此可以对其应用同步.此外,如果数组存储对象,我应该能够同步数组的每个元素.
我的程序有几个线程更新了一个数组,因此我创建了一个Long对象数组:
synchronized (grid[arrayIndex]){
grid[arrayIndex] += a.getNumber();
}
Run Code Online (Sandbox Code Playgroud)
这段代码位于run()我扩展的线程类的方法中.数组网格由我的所有线程共享.但是,在一个线程上运行相同的程序时,这不会返回正确的结果.
我正在尝试在 CUDA 中编写程序,但我在线程之间的同一块中遇到同步问题。
这是模型情况:
10 __global__ void gpu_test_sync()
11 {
12 __shared__ int t;
13 int tid = threadIdx.x;
14
15 t = 0;
16 __threadfence();
17 __syncthreads();
18
19 // for(int i=0; i<1000000 && t<tid; i++); // with fuse
20 while(t<tid);
21
22 t++;
23 __threadfence();
24 }
25
26 void f_cpu()
27 {
28 printf("TEST ... ");
29 int blocks = 1;
30 int threads = 2;
31 gpu_test_sync<<< blocks , threads >>>();
32 printf("OK\n");
33 }
Run Code Online (Sandbox Code Playgroud)
如果线程数 …
如果我没有该应用程序的源代码,如何在正在运行的C#应用程序中找到命名的互斥锁?
阅读短语"当前的SynchronizationContext是当前线程的属性"更正",我有点困惑......
在VS2010中的C#应用程序代码中,当我输入时,Thread.CurrentThread.我没有在Intellisense给出的选项的下拉列表中找到线程的任何上下文相关属性.
我知道当前的同步上下文可以通过" = SynchronizationContext.Current;"获得.但是,并行线程,任务等同时执行并不是很幸运.
假设从一个控制台或WPF (*)应用程序,我在自己的主UI线程和TPL任务中创建并启动一些Windows窗体.
我认为每个winform都应该有自己的WindowsFormaSynchronizationContext,WPF应该有自己的DispatcherSynchronizationContext(SynchronizationContext类的子类)实例,任务在ThreadPool中用自己的同步上下文 执行,LongRunning任务也可以在其中执行线程池.拥有同步上下文......
那么,为什么不能SynchronizationContext从线程中定义?"从给定线程中获取同步语言"问题的所有答案似乎都不一致否定了这种可能性......
最后,但并非最不重要:
短语"当前SynchronizationContext是当前线程的属性"正确"正确吗?
那么,我怎样才能获得不同特定线程实例的此属性的值?
(*)
最近,我基本上使用winforms获得了C#WPF应用程序代码.
c# multithreading synchronizationcontext task-parallel-library thread-synchronization
我有一段这样的代码:
public class UserCache
{
private Dictionary<int, User> _users = new Dictionary<int, User>();
public User GetUser(int id)
{
User u = null;
lock (_users)
{
if (_users.containsKey(id))
return _users[id];
}
//The below line is threadsafe, so no worries on that.
u = RetrieveUser(id); // Method to retrieve from database;
lock (_users)
{
_users.Add(id, u);
}
return u;
}
}
Run Code Online (Sandbox Code Playgroud)
我正在锁定对字典的访问权限,但我团队中有人告诉它仍然没有线程安全(没有解释).问题是 - 你认为这是线程安全的吗?
编辑:忘了询问,解决方案是什么样的.请注意我不想锁定整个方法,因为检索用户是一个耗时的操作.
我只是好奇线程 T1 是否有可能部分执行同步块,然后释放对象上的锁,而另一个线程 T2 执行同一块?像这样的东西:
line1: synchronized(this){
line2: if(INSTANCE == null)
line3: INSTANCE = new Object(); //say a variable is initialized
line4: return INSTANCE;
line5: }
Run Code Online (Sandbox Code Playgroud)
线程 T1 是否有可能获取当前对象 ( this) 的锁并执行 line1 和 line2。然后线程 T1 被线程 T2 抢占,T1 释放锁,T2 获取锁this并执行同一块(所有行 1 到 5)。然后线程T1再次获得锁并继续从第3行开始执行?
基本上,T1 将被视为INSTANCEnull,T2 也将被视为 null,并且每个对象都会创建一个新对象。
如果这是不可能的,有人可以解释为什么不可以吗?
附录:
谢谢大家的回答。我的问题有点误导。我到底想问的是,一旦一个线程执行同步块,它是否可以在整个块执行之前释放锁(不是通过显式调用,wait()而是依赖于进程、CPU)?JLS 或 JVM 中是否有约定保证一旦线程开始执行同步块,对象上的锁直到块结束才被释放?我的理解是同步保证没有2个线程可以同时执行该块(或其他同步方法/块),但锁会一直保持到到达块末尾?这很明显,但是 JLS 中有指定吗?
编辑:这不是任何允许在 post() 中互斥锁定的问题的重复。请仔细阅读,我需要一个无锁帖子()!如果您没有真正的答案,请不要标记此重复项。
信号量(如在 Linux 中)是一个有用的构建块,但在 C++ 标准中没有找到,在 boost(目前)中也没有。我主要讨论的是抢占式调度程序中单个进程的线程之间的信号量。
我对它们的非阻塞(即无锁)特别感兴趣,除非它实际上需要阻塞。也就是说,post() 和 try_wait() 应该始终是无锁的。如果 wait() 调用强烈发生在足够的 post() 返回之后,那么 wait() 调用应该是无锁的。此外,阻塞 wait() 应该被调度程序阻塞而不是自旋锁定。如果我还想要一个带有超时的 wait_for 该怎么办 - 它会使实现进一步复杂化,同时仍然避免饥饿?
信号量不在标准中是否有原因?
Edit3:所以,我不知道有一个针对标准 P0514R4 的提案可以准确处理这些问题,并且除了专门添加 std::semaphore 之外,还可以解决此处提出的所有问题。http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0514r4.pdf
而且boost没有这些。具体来说,进程间的进程是自旋锁定的。
哪些库支持类似的东西?
是否可以通过 windows api 和其他广泛的系统来实现它?
编辑:不可能使用原子+互斥体+条件变量来实现无锁 - 您要么必须在发布中阻塞,要么在等待中旋转。如果您想要无锁的 post(),则不能在 post() 中锁定互斥体。我想在可能抢占式的调度程序上运行,并且我不希望 post() 被其他获取互斥锁并被抢占的线程阻塞。那么,这不是像C++0x has no semaphores 这样的问题的重复吗?如何同步线程?
edit2:下面的示例实现只是为了演示使用atomics+mutex+condvar可以完成的最佳操作,据我所知。post() 和 wait() 执行一次无锁比较交换,并且只有在必须时,它们才会锁定互斥锁。
然而 post() 不是无锁的。更糟糕的是,它可能会被锁定互斥锁并被抢占的 wait() 阻塞。
为了简单起见,我只实现了 post_one() 和 wait_one_for(Duration),而不是 post(int) 和 wait_for(int,Duration)。另外,我假设标准没有承诺无虚假唤醒。
class semaphore //provides acquire release memory ordering for the …Run Code Online (Sandbox Code Playgroud) 我有一个线程需要阻塞,直到另一个线程发生某些事情。这听起来很典型,我有这个解决方案。
//thread 1
mux.lock();
//send work to another thread
mux.lock(); //will likely block which I want
//thread 2
//get the work sent over from thread 1
//work on it, then
mux.unlock(); //unblock thread 1 - all good
Run Code Online (Sandbox Code Playgroud)
这似乎在 Linux 上运行良好,并且不需要条件变量 - 除了 C++ 标准说在同一线程中两次获取锁是未定义的行为 - 我在线程 1 中这样做。
我有两个关于__syncwarp()CUDA的问题:
__syncwarp()作用,为什么有必要?__syncthreads()有用,但由于块被分割成的扭曲可能与组不匹配,如何保证使用时的正确性__syncwarp()?我使用 ASP.NET Core Identity,通过 Jmeter 应用程序,我向我的 Web 应用程序发送多个请求以创建用户,它使用同一电子邮件创建了多个用户,尽管我的RequireUniqueEmail是true
services.AddIdentity<User, Role>(identityOptions =>
{
identityOptions.User.RequireUniqueEmail = true;
});
Run Code Online (Sandbox Code Playgroud)
当我一一发送请求时,一切正常,并在这段代码中给我重复的电子邮件错误
var result = await _userManager.CreateAsync(userToCreate, userPassword);
Run Code Online (Sandbox Code Playgroud)
但是当我使用 Jmeter 发送多个请求时,上面的代码无法处理重复的电子邮件,并且在 Jmeter 请求完成后,我打开 SQL Server,我看到至少创建了 10 条具有相同电子邮件的记录。我搜索了这个问题并得到了这个解决方案Using lock
private static readonly object lockObj = new object();
lock(lockObj)
{
var result = await _userManager.CreateAsync(userToCreate, userPassword);
}
Run Code Online (Sandbox Code Playgroud)
但它给了我错误并说“你不能在锁定语句中使用await”,第二个问题是ASP.NET Core Identity没有用于创建的Sync方法。如何在 ASP.NET Core Identity 中创建 create 的同步方法?
c# multithreading thread-synchronization async-await asp.net-core