我是否可以为此方案设计任何无锁解决方案

本文关键字:方案设计 任何无 解决方案 是否 | 更新日期: 2023-09-27 18:37:14

>我有一个简单的员工类,如下所示

public class Employee
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
    }

然后,我有一个ProcessEmployees类,它以称为ProcessThisEmployee的方法对这些员工进行并发处理。在此方法中,我必须调用第三方库方法。到目前为止,一切都很简单。问题是有时当用户选择在此操作进行时取消此操作时,我需要对尚未完成处理的任何第三方库类实例进行一些清理。注意 我对第三方库类没有任何控制权,它没有任何取消现有任务的机制。它确实提供了一个 Clean 方法,我可以在调用 SomeAPI 尚未完成的任何实例上调用该方法。因此,我正在维护所有实例的本地列表。当用户选择取消操作时,我调用我的类的 CleaupIfUserCancelOperation 方法,即我的本地列表中的这个第三方库实例的 Clean 方法。下面是我的代码。

class ProcessEmployees
{
    private List<Employee> _Employees;
    List<ThirdPartyLibrary> libraries = new List<ThirdPartyLibrary>();
    private object sync = new object();
    public  ProcessEmployees()
    {
        _Employees = new List<Employee>() 
        {
            new Employee() { ID = 1, FirstName = "John", LastName = "Doe" },
            new Employee() { ID = 2, FirstName = "Peter", LastName = "Saul" },
            new Employee() { ID = 3, FirstName = "Mike", LastName = "Sue" },
            new Employee() { ID = 4, FirstName = "Catherina", LastName = "Desoza" },
            new Employee() { ID = 5, FirstName = "Paul", LastName = "Smith" }
        };
    }
    public void StartProcessing()
    {
        Task[] tasks = this._Employees.AsParallel().Select(x => this.ProcessThisEmployee(x)).ToArray();
        Task.WaitAll(tasks);
        // other stuff
    }
    private async Task ProcessThisEmployee(Employee x)
    {
        ThirdPartyLibrary library = new ThirdPartyLibrary();
        lock (sync)
        {
            libraries.Add(library);
        }
        await Task.Factory.StartNew(() => library.SomeAPI(x) );
        lock (sync)
        {
            libraries.Remove(library);
        }
    }
    private void CleaupIfUserCancelOperation()
    {
        foreach (ThirdPartyLibrary library in libraries)
            library.Clean();
    }
}

我必须在此处锁定库实例两次,这当然会影响性能。在这种情况下可以使用任何轻量级(无锁)机制吗?我对并发收集了解不多,想知道它们在这种情况下是否有任何用处?

我是否可以为此方案设计任何无锁解决方案

这两个锁定调用对性能的影响很可能比您正在执行的其余调用小得多。假设它们这样做,您可以使用ConcurrentDictionary来添加和删除实例(无论如何您都不应该使用 List,因为现在并发库的数量具有二次性能开销)。

最好让每个异步方法自行取消并清理自己的内容。给他们传CancellationToken.使用 Register 注册清理库的回调。这里真的不需要全局状态/集合。