我试图实现我自己的自定义SpinLock,但SpinLock似乎行为不端。
我有两个文件,main.rs
和safe.rs
。
测试在Ubuntu 22.04.3LTS中完成,系统规格为4GB RAM,64位处理器,AMD® Pro a4- 3350 b APU和Radeon r4显卡。
下面是错误消息:
loki@loki:~/main/vs/actic/rust-nomic/spin-lock$ cargo run RUST_BACKTRACE=1
Compiling spin-lock v0.1.0 (/home/loki/main/vs/actic/rust-nomic/spin-lock)
Finished dev [unoptimized + debuginfo] target(s) in 0.98s
Running `target/debug/spin-lock RUST_BACKTRACE=1`
Hello, world!
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `9999995`,
right: `10000000`', src/main.rs:15:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
字符串safe.rs
:
use core::ops::{Deref,DerefMut};
use core::sync::atomic::{AtomicBool,Ordering::{Acquire,Release}};
use core::cell::UnsafeCell;
use core::hint::spin_loop;
#[derive(Debug)]
pub struct SpinLock<T>{
// Status true -> its locked || Status false -> its un_locked(ready to lock)
status:AtomicBool,
pub data:UnsafeCell<T>
}
pub struct SpinGuard<'a,T>{
lock:&'a SpinLock<T>
}
unsafe impl<T> Sync for SpinLock<T> where T:Send{}
impl<T> SpinLock<T>{
#[inline]
pub const fn new(data:T)->Self{
Self { status: AtomicBool::new(false), data: UnsafeCell::new(data) }
}
pub fn lock(&self)->SpinGuard<T>{
while self.status.swap(true,Acquire){
spin_loop();
}
SpinGuard { lock: self }
}
}
impl<'a,T> SpinGuard<'a,T>{
pub fn release(self){
self.lock.status.store(false, Release)
}
}
impl<T> Deref for SpinGuard<'_,T>{
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe{&*self.lock.data.get()}
}
}
impl<T> DerefMut for SpinGuard<'_,T>{
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe{&mut *self.lock.data.get()}
}
}
impl<T> Drop for SpinGuard<'_,T>{
fn drop(&mut self) {
self.lock.status.store(false, Release)
}
}
型main.rs
:
use std::thread;
mod safe;
fn main() {
println!("Hello, world!");
let mut x=safe::SpinLock::new(0);
thread::scope(|t|{
for _ in 0..10000000{
t.spawn(||{
let mut q=x.lock();
*q+=1;
q.release();
});
}
});
assert_eq!(x.data.get_mut(),&mut 10000000);
println!("{:?}",x);
}
型
1条答案
按热度按时间4ktjp1zp1#
通过添加几个
sleep
,您可以使错误更具可重复性:个字符
原因是你解锁了两次,这有点隐藏,但
.release()
函数实际上直接解锁了一次,在drop()
函数中解锁了一次。只需删除
.release()
函数中的第一个解锁,然后它就可以工作了:)作为另一个吹毛求疵的人,我会用
AcqRel
替换swap
中的Acquire
,但我不能100%肯定这会有什么不同。的字符串