@synchronized不使用"锁定"和"解锁"来实现互斥吗?那怎么做锁定/解锁呢?
以下程序的输出仅为"Hello World".
@interface MyLock: NSLock<NSLocking>
@end
@implementation MyLock
- (id)init {
return [super init];
}
- (void)lock {
NSLog(@"before lock");
[super lock];
NSLog(@"after lock");
}
- (void)unlock {
NSLog(@"before unlock");
[super unlock];
NSLog(@"after unlock");
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyLock *lock = [[MyLock new] autorelease];
@synchronized(lock) {
NSLog(@"Hello World");
}
[pool drain];
}
Run Code Online (Sandbox Code Playgroud) 假设我在Swift中有以下类(它有明显的问题)
class MyClass {
let myProperty: String
init() {
super.init()
self.setupMyProperty()
}
func setupMyProperty() {
myProperty = "x"
}
}
Run Code Online (Sandbox Code Playgroud)
这是过度简化,但我基本上试图将初始化委托myProperty给setupMyProperty()方法.这是我经常使用的模式来分解类的设置的不同部分.
但是当然,self在超级初始化程序运行之前我无法调用,并且在所有属性都已设置之前我无法运行超级初始化程序,因此我处于捕获状态22.最重要的是它setupMyProperty()不是被认为是初始化程序,myProperty无论如何都无法分配.
谁能告诉我如何在Swift中实现这种模式?
我的应用程序需要一个读/写锁.我读过 https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock
并编写了我自己的类,因为swift中没有读/写锁
class ReadWriteLock {
var logging = true
var b = 0
let r = "vdsbsdbs" // string1 for locking
let g = "VSDBVSDBSDBNSDN" // string2 for locking
func waitAndStartWriting() {
log("wait Writing")
objc_sync_enter(g)
log("enter writing")
}
func finishWriting() {
objc_sync_exit(g)
log("exit writing")
}
// ???? ???? ??? ?????? ?????????? ????? ?????? ??????
// ? ????????? ??????
func waitAndStartReading() {
log("wait reading")
objc_sync_enter(r)
log("enter reading")
b++
if b == 1 {
objc_sync_enter(g)
log("read lock writing")
}
print("b = …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
func foo() {
var sum = 0
var pendingElements = 10
for i in 0 ..< 10 {
proccessElementAsync(i) { value in
sum += value
pendingElements--
if pendingElements == 0 {
println(sum)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,函数proccessElementAsync,如其名称所示,异步处理其输入参数,并在完成时调用其相应的完成处理程序.
这种方法的不便之处在于,由于变量pendingElements是通过多个线程访问的,因此该语句if pendingElements == 0可能永远不会为true.
在C#中,我们可以做类似的事情:
Object lockObject = new Object();
...
lock (lockObject) {
pendingElements--;
if (pendingElements == 0) {
Console.WriteLine(sum);
}
}
Run Code Online (Sandbox Code Playgroud)
这确保了只能为一个线程同时访问此变量.有没有办法在Swift中获得相同的行为?
我在Swift 3中创建了一个简单的单例:
class MySingleton {
private var myName: String
private init() {}
static let shared = MySingleton()
func setName(_ name: String) {
myName = name
}
func getName() -> String {
return myName
}
}
Run Code Online (Sandbox Code Playgroud)
由于我创建了init()私有的,也声明了shared实例static let,我认为初始化程序是线程安全的.但是getter和setter函数myName呢,它们是否安全?
Mike Ash撰写了一篇关于Swift构建的轻量级通知系统的精彩文章:(https://www.mikeash.com/pyblog/friday-qa-2015-01-23-lets-build-swift-notifications.html).
基本思路是创建可以"监听"的对象,即在状态发生变化时调用回调.为了使其成为线程安全的,每个创建的对象都拥有自己的dispatch_queue.dispatch_queue仅用于对关键部分进行门控:
dispatch_sync(self.myQueue) {
// modify critical state in self
}
Run Code Online (Sandbox Code Playgroud)
此外,它可能不会有很高的争议.令我感到震惊的是,您创建的每个可以侦听的对象都会创建自己的调度队列,这只是为了锁定几行代码.
一张海报表明OS_SPINLOCK会更快更便宜; 也许,但它肯定会使用更少的空间.
如果我的程序创建了数百或数千(甚至数万个对象),我是否应该担心创建这么多的调度队列?可能大多数人甚至都不会被倾听,但有些人可能会听.
当然有两个对象不会相互阻塞,也就是说有单独的锁,这是有道理的.通常我不会考虑在每个对象中嵌入pthread_mutex,而是整个调度队列?那真的好吗?
我正在尝试创建一个线程安全的属性包装器。我只能认为 GCD 队列和信号量是最快速、最可靠的方式。信号量只是更高的性能(如果这是真的),还是有另一个理由使用一个而不是另一个来实现并发?
以下是原子属性包装器的两种变体:
@propertyWrapper
struct Atomic<Value> {
private var value: Value
private let queue = DispatchQueue(label: "Atomic serial queue")
var wrappedValue: Value {
get { queue.sync { value } }
set { queue.sync { value = newValue } }
}
init(wrappedValue value: Value) {
self.value = value
}
}
@propertyWrapper
struct Atomic2<Value> {
private var value: Value
private var semaphore = DispatchSemaphore(value: 1)
var wrappedValue: Value {
get {
semaphore.wait()
let temp = value
semaphore.signal()
return temp
}
set …Run Code Online (Sandbox Code Playgroud) 我看到这个函数在UISearchBarDelegate方法textDidChange中使用.我查看了所有文档并且无法提出任何建议.只是想知道是否有人可以阐明这个功能正在做什么.
objc_sync_exit(self)
Run Code Online (Sandbox Code Playgroud) 根据这个问题的答案,我对以下两种同步方法的简单性和易用性感到满意:
func synchronized(lock: AnyObject, closure: () -> Void) {
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
}
func synchronized<T>(lock: AnyObject, closure: () -> T) -> T {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return closure()
}
Run Code Online (Sandbox Code Playgroud)
但是为了确保它们实际上正在做我想要的东西,我想用成堆的单元测试来包装它们.如何编写有效测试这些方法的单元测试(并显示它们实际上正在同步代码)?
理想情况下,我也希望这些单元测试尽可能简单明了.据推测,此测试应该是代码,如果在同步块之外运行,将提供一组结果,但在这些同步块内提供完全独立的结果集.
我经历了这个问题,但提供的解决方案不起作用。有人可以使用 os_unfair_lock() 解释任何替代方法或正确实现吗?
当我使用“OS_UNFAIR_LOCK_INIT”时,它似乎不可用。
谢谢!
swift ×8
ios ×3
concurrency ×1
objective-c ×1
semaphore ×1
spinlock ×1
swift3 ×1
unit-testing ×1