关于race condition的思考

本文详细阐述了racecondition的概念,特别是在多线程编程中共享资源访问时可能出现的问题,并通过实例分析展示了racecondition的原理及危害。文章进一步探讨了解决racecondition的方法,包括使用互斥锁确保共享资源的原子访问,旨在提升程序的并发性和稳定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所谓race condition就是因为语句执行顺序的不同,从而造成程序运行结果不同的一种情况。
单线程编程是不可能出现race condition的情况;如果你的共享资源是原子操作,那也不会出现
race condition,但是对于共享资源,哪怕只是一个全局变量的访问,也无法保证其原子性。
在单处理器系统中,真正的原子操作是能够在一个指令周期内完成的操作都能称为原子操作;
而在多处理器系统中,却无法真正做到原子性。
通常race condition只会发生在多线程编程时,对共享资源的访问。

race condition案例分析:
首先定义全局共享变量
int g_pshared_resource;

int get_shared_resource(void)
{
    return g_pshared_resource;
}

void set_shared_resource(int value)
{
    g_pshared_resource = value;
}

thread_A中执行:
if (get_shared_resource() != null)
{
    process_resource();
}

thread_B中执行:
set_shared_resource(value);

所以程序的实际运行顺序就可能会变成:
thread_A get_shared_resource(), get OK;
thread_B set_shared_resource(), set OK;
thread_A process_resource(), 而此时g_pshared_resource已经被修改。

如果是这种case的race condition,此时我们单纯的使用一个mutex无法解决问题。
void get_shared_resource(int* pvalue)
{
    mutex_lock();
    *pvalue = g_pshared_resource;
    mutex_unlock();
}

void set_shared_resource(int value)
{
    mutex_lock();
    g_pshared_resource = value;
    mutex_unlock();
}
上面的代码只能保证对g_pshared_resource这个共享资源的互斥访问,
但是仍然无法解决上述的race condition问题。

正确的做法是需要两把锁,一把锁实现对g_pshared_resource的互斥访问;
另一把锁来实现整个访问过程的原子性。

g_mutex_lock();
if (get_shared_resource() != null)
{
    process_resource();
}
g_mutex_unlock();

待解决问题:
软件上如何实现操作的原子性,还有待确认;
对共享变量的读写是否也要实现互斥访问?

--------------------------------------------------------------------------- PermissionError Traceback (most recent call last) Cell In[70], line 1 ----> 1 train_iter, test_iter = load_data_fashion_mnist(32, resize=64) 2 for X, y in train_iter: 3 print(X.shape, X.dtype, y.shape, y.dtype) Cell In[69], line 7, in load_data_fashion_mnist(batch_size, resize) 5 trans.insert(0, transforms.Resize(resize)) 6 trans = transforms.Compose(trans) ----> 7 mnist_train = torchvision.datasets.FashionMNIST( 8 root="../data", train=True, transform=trans, download=True) 9 mnist_test = torchvision.datasets.FashionMNIST( 10 root="../data", train=False, transform=trans, download=True) 11 return (data.DataLoader(mnist_train, batch_size, shuffle=True, 12 num_workers=get_dataloader_workers()), 13 data.DataLoader(mnist_test, batch_size, shuffle=False, 14 num_workers=get_dataloader_workers())) File E:\Anaconda\envs\d2l\lib\site-packages\torchvision\datasets\mnist.py:100, in MNIST.__init__(self, root, train, transform, target_transform, download) 97 return 99 if download: --> 100 self.download() 102 if not self._check_exists(): 103 raise RuntimeError("Dataset not found. You can use download=True to download it") File E:\Anaconda\envs\d2l\lib\site-packages\torchvision\datasets\mnist.py:180, in MNIST.download(self) 177 if self._check_exists(): 178 return --> 180 os.makedirs(self.raw_folder, exist_ok=True) 182 # download files 183 for filename, md5 in self.resources: File E:\Anaconda\envs\d2l\lib\os.py:215, in makedirs(name, mode, exist_ok) 213 if head and tail and not path.exists(head): 214 try: --> 215 makedirs(head, exist_ok=exist_ok) 216 except FileExistsError: 217 # Defeats race condition when another thread created the path 218 pass File E:\Anaconda\envs\d2l\lib\os.py:215, in makedirs(name, mode, exist_ok) 213 if head and tail and not path.exists(head): 214 try: --> 215 makedirs(head, exist_ok=exist_ok) 216 except FileExistsError: 217 # Defeats race condition when another thread created the path 218 pass File E:\Anaconda\envs\d2l\lib\os.py:225, in makedirs(name, mode, exist_ok) 223 return 224 try: --> 225 mkdir(name, mode) 226 except OSError: 227 # Cannot rely on checking for EEXIST, since the operating system 228 # could give priority to other errors like EACCES or EROFS 229 if not exist_ok or not path.isdir(name): PermissionError: [WinError 5] 拒绝访问。: '../data'shenmeyisi
03-09
<think>好的,我现在需要帮用户解决他们遇到的PermissionError问题。首先,我得仔细看看他们提供的错误信息。用户在使用PyTorch加载FashionMNIST数据集时,报错显示在创建目录'../data'时被拒绝访问。错误发生在调用os.makedirs时,具体是权限问题。 首先,我应该分析可能的原因。权限问题通常发生在用户没有足够的权限在指定目录下创建文件或文件夹。用户指定的路径是'../data',也就是当前工作目录的上层目录下的data文件夹。可能用户当前运行脚本的环境没有权限访问上层目录,尤其是在Windows系统上,某些目录可能需要管理员权限才能写入。 接下来,我应该考虑常见的解决方案。首先,建议用户检查路径是否正确,确认是否有权限写入该目录。如果用户没有权限,可能需要更改数据存储的路径到用户有权限的地方,比如当前项目目录下的data文件夹,而不是上层目录。或者,用户可能需要以管理员身份运行程序,但这种方法不太安全,一般不推荐。 另外,用户可能误用了相对路径。比如,如果脚本的运行位置不是在预期的目录下,'../data'可能指向了一个受保护的位置。这时候,建议用户使用绝对路径,或者调整相对路径,确保目标目录在可写的位置。例如,直接使用'data'而不是'../data',这样数据会保存在当前目录的data文件夹中,通常不会有权限问题。 还需要检查是否存在目录创建的问题。可能用户手动创建了该目录,但权限设置不正确。可以建议用户手动创建data目录,并赋予适当的权限。此外,代码中是否有其他部分正在占用该目录,导致无法访问?比如,另一个进程可能正在使用该目录,导致写入失败。 另一个可能性是防病毒软件或安全软件阻止了写入操作。用户可以暂时禁用这些软件,看是否能解决问题。不过,这需要谨慎处理,确保系统安全。 然后,我应该将这些思考整理成步骤,逐步指导用户解决问题。首先确认路径问题,建议修改路径到可写的位置,然后检查权限,最后考虑其他可能因素。同时,需要给出具体的代码修改示例,比如将root参数改为'./data',并说明如何确保目录可写。 最后,确保回答结构清晰,用中文简洁明了地解释问题原因,并提供可行的解决方案,帮助用户逐步排查和解决问题。同时,注意使用符合规定的LaTeX格式,但在这个问题中可能用不上数学公式,所以主要关注代码和路径的格式。</think>这个错误是文件权限问题导致的,说明程序没有权限在指定路径创建/写入数据文件。我们逐步分析并解决: 1. **错误定位**: 错误发生在`os.makedirs`尝试创建`../data`目录时触发`PermissionError: [WinError 5]`,说明: - 当前用户没有上级目录(`../`)的写入权限 - 程序可能试图向系统保护区域写数据 2. **常见解决方案**: **方案一:修改数据存储路径** ```python # 将 root 参数改为当前目录下的 data 文件夹 mnist_train = torchvision.datasets.FashionMNIST( root="./data", # 改为当前目录(而非上级目录) train=True, transform=trans, download=True) ``` **方案二:手动创建目录** ```bash # 在项目根目录执行 mkdir data # 然后重新运行程序 ``` **方案三:以管理员身份运行(不推荐)** - 右键点击运行程序/IDE -> 以管理员身份运行 - 适用于需要写入系统目录的特殊情况 3. **路径验证建议**: ```python import os print(os.path.abspath("../data")) # 检查实际路径是否合法 # 输出示例:E:\protected_system_path\data(说明路径不安全) ``` 4. **附加检查项**: - 确认`data`目录没有被其他程序占用 - 检查防病毒软件是否阻止了目录创建 - 如果是共享服务器环境,联系管理员设置权限 建议优先采用方案一,将数据存储在项目自身目录中。修改后的路径结构应该是: ``` your_project/ ├── your_code.py └── data/ # 程序自动创建并下载数据到这里 ``` > 注意:在Windows系统中,直接尝试写入`Program Files`等系统目录会触发此类错误,保持数据存储在用户有写权限的项目目录是最佳实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值