【问题标题】:Issue in synchronization of method when called from different application从不同应用程序调用时方法同步问题
【发布时间】:2016-12-23 09:44:07
【问题描述】:

我有一个名为 API 的类库应用程序。在其中我有一个名为 SynchronizeMe 的方法。

 public class APIClass
    {
        object baton = new object();
        static int count = 0;
        public void SynchronizeMe()
        {
            while(true)
            {
                lock (baton)
                {
                    int temp = count;
                    Thread.Sleep(5000);
                    count = temp + 1;

                    Console.WriteLine("Thread Id " + Thread.CurrentThread.ManagedThreadId + " Name:" + Thread.CurrentThread.Name + " incremented count to " + count);
                }
                Thread.Sleep(1000);
            }

        }
    }

我有两个控制台应用程序 Thread1 和 Thread2。他们都调用了 SynchronizeMe 方法。 喜欢

 API.APIClass apicall = new API.APIClass();
 apicall.SynchronizeMe();

当我运行它时,我看到它们的打印计数都从 1 开始。这意味着它没有同步。我理解多线程的概念有什么问题吗?还是代码有问题?或者同一应用程序中的线程只能同步。如果我想以这种方式同步是什么方式?

我认为 Thread1 和 Thread2 都有不同的 APIClass 实例,因此无法同步。有什么出路吗?

【问题讨论】:

  • 澄清一下,您是否有两个单独运行的控制台应用程序调用库,或者单个控制台应用程序中有两个线程?
  • @user783836 两个单独运行的控制台应用程序。
  • @TBAG 看看我的答案

标签: c# multithreading c#-4.0


【解决方案1】:

如果您有两个单独的控制台应用程序,使用 lock 关键字的锁不会在它们之间共享 - lock 是单个进程的本地应用程序。

如果您想跨进程锁定,则需要改用named mutex

http://www.c-sharpcorner.com/UploadFile/1d42da/threading-with-mutex/

有关使用互斥锁的跨进程锁定,请参阅http://mikeperetz.blogspot.co.uk/2013/12/cross-process-locking-using-named-mutex.html

您的代码如下所示:

    public class APIClass
{
    private const string MutexName = "FAA9569-7DFE-4D6D-874D-19123FB16CBC-8739827-[SystemSpecicString]";
    private Mutex _globalMutex;
    private bool _owned = false;
    private int timeToWait = 1000;

    object baton = new object();
    static int count = 0;
    public void SynchronizeMe()
    {
        _globalMutex = new Mutex(true, MutexName, out _owned);
        while(true)
        {
            while (!_owned)
            {
                // did not get the mutex, wait for it.
                _owned = _globalMutex.WaitOne(timeToWait);
            }

            int temp = count;
            Thread.Sleep(5000);
            count = temp + 1;

            Console.WriteLine("Thread Id " + Thread.CurrentThread.ManagedThreadId + " Name:" + Thread.CurrentThread.Name + " incremented count to " + count);
            // release the mutex
            _globalMutex.ReleaseMutex();
            Thread.Sleep(1000);
        }

    }
}

【讨论】:

  • 虽然同步可以工作,但它仍然不会在进程之间使用相同的计数器变量。
  • @nvoigt 公平点,OP 不清楚这是目标还是只是为了理解跨进程同步
  • @user783836 第二个线程无法获取锁。只有 thread1 是打印值。第二个控制台什么也没有。
  • @TBAG 这是因为两个进程都不会产生锁。您在原始问题中的代码有同样的问题。我已经更新了代码示例以产生锁。但是请注意,正如@nvoigt 指出的那样,没有变量(例如count)在进程之间共享。为此,您需要内存映射文件或类似文件。
  • @user783836 以前的代码在两个控制台中打印。共享计数变量对我来说并不重要。
【解决方案2】:

两个进程(或者更确切地说是两个应用程序域)将加载您库的两个完全独立的副本

因此,您的lock 不仅会锁定调用程序集的副本,而且您的count 变量也将作为两个单独的副本存在。

您可以与例如mutex 进行与进程无关的同步,但您仍然需要找到一种方法来共享该计数器。这可以像将其保存在文件或注册表项中一样简单,也可以使用数据库。但是,如果您想将其保存在内存中,则需要启动第三个进程,而不是将每个库的副本加载到现有进程中。这意味着您将需要inter process communication

【讨论】:

    猜你喜欢
    • 2010-09-18
    • 2017-09-23
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 2021-09-23
    • 1970-01-01
    相关资源
    最近更新 更多