আমি সুইফট বইটি সন্ধান করেছি, কিন্তু @ সিনক্রোনাইজডের সুইফট সংস্করণটি খুঁজে পাই না। আমি কীভাবে সুইফটে পারস্পরিক বর্জন করব?
removeFirst()
?
আমি সুইফট বইটি সন্ধান করেছি, কিন্তু @ সিনক্রোনাইজডের সুইফট সংস্করণটি খুঁজে পাই না। আমি কীভাবে সুইফটে পারস্পরিক বর্জন করব?
removeFirst()
?
উত্তর:
আপনি জিসিডি ব্যবহার করতে পারেন। এটি এর চেয়ে কিছুটা ভারবস @synchronized
, তবে প্রতিস্থাপন হিসাবে কাজ করে:
let serialQueue = DispatchQueue(label: "com.test.mySerialQueue")
serialQueue.sync {
// code
}
আমি এটি নিজের জন্য সন্ধান করছিলাম এবং এই সিদ্ধান্তে পৌঁছেছি যে এটার জন্য দ্রুত কোনও অভ্যন্তরীণ নির্মাণ নেই।
আমি ম্যাট ব্রিজ এবং অন্যদের থেকে দেখেছি এমন কয়েকটি কোডের উপর ভিত্তি করে এই ছোট সহায়ক সাহায্যকারীর কাজটি করেছি।
func synced(_ lock: Any, closure: () -> ()) {
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
}
ব্যবহার বেশ সোজা এগিয়ে
synced(self) {
println("This is a synchronized closure")
}
এটির সাথে একটি সমস্যা খুঁজে পেয়েছি। লক আর্গুমেন্ট হিসাবে একটি অ্যারে পাস করার ফলে এই মুহুর্তে খুব অবসন্ন সংকলক ত্রুটি দেখা দেয়। অন্যথায় যদিও এটি পছন্দসই হিসাবে কাজ করে বলে মনে হচ্ছে।
Bitcast requires both operands to be pointer or neither
%26 = bitcast i64 %25 to %objc_object*, !dbg !378
LLVM ERROR: Broken function found, compilation aborted!
@synchronized
ব্লকের বাক্য গঠনটি সুন্দরভাবে সংরক্ষণ করে তবে লক্ষ্য করুন যে এটি @synchronized
অবজেক্টিভ-সি-তে ব্লকের মতো বাস্তব বিল্টিন ব্লক স্টেটমেন্টের মতো নয় , কারণ return
এবং break
বিবৃতিগুলি আর পার্শ্ববর্তী ফাংশন / লুপের বাইরে চলে যাওয়ার পক্ষে কাজ করে না like এটা যদি এটি একটি সাধারণ বিবৃতি হয়।
defer
কীওয়ার্ডটি ব্যবহার করার জন্য দুর্দান্ত জায়গা হতে পারে তা ছোঁড়ার objc_sync_exit
পরেও কল হয়ে যায় তা নিশ্চিত করে closure
।
আমি এখানে অনেক উত্তর পছন্দ এবং ব্যবহার করি, তাই আমি আপনার জন্য যে কোনটি ভাল কাজ করে তা চয়ন করব। এটি বলেছিল, যখন আমার উদ্দেশ্য-সি এর মতো কিছু দরকার তখন আমি যে পদ্ধতিটি পছন্দ করি তা সুইফট 2-এ প্রবর্তিত বিবৃতি @synchronized
ব্যবহার করে defer
।
{
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
//
// code of critical section goes here
//
} // <-- lock released when this block is exited
এই পদ্ধতি সম্পর্কে চমৎকার জিনিস, যে আপনার সমালোচনামূলক ধারা পছন্দসই কোনো ফ্যাশন ধারণকারী ব্লক থেকে প্রস্থান করতে পারেন (যেমন, return
, break
, continue
, throw
), এবং "মুলতবি বিবৃতি মধ্যে বক্তব্য কোন ব্যাপার কিভাবে প্রোগ্রাম কন্ট্রোলের স্থানান্তর করা হয় মৃত্যুদন্ড কার্যকর করা হয়।" 1
lock
? কীভাবে শুরু করা lock
হয়?
lock
যেকোন উদ্দেশ্য-সি বস্তু।
আপনি objc_sync_enter(obj: AnyObject?)
এবং এর মধ্যে বিবৃতি স্যান্ডউইচ করতে পারেন objc_sync_exit(obj: AnyObject?)
। @ সিংক্রোনাইজড কীওয়ার্ডটি কভারগুলির আওতায় সেই পদ্ধতিগুলি ব্যবহার করছে। অর্থাত
objc_sync_enter(self)
... synchronized code ...
objc_sync_exit(self)
objc_sync_enter
এবং objc_sync_exit
ওবজেসি-সিঙ্ক.হ. এ সংজ্ঞায়িত পদ্ধতিগুলি এবং ওপেন সোর্স: ওপেনসোর্স.এপল
objc_sync_enter(…)
এবং objc_sync_exit(…)
আইওএস / ম্যাকোস / ইত্যাদি দ্বারা সরবরাহিত সর্বজনীন শিরোনাম। API গুলি (দেখে মনে হচ্ছে এগুলি ….sdk
পথের ভিতরে রয়েছে usr/include/objc/objc-sync.h
) । কোনও কিছু পাবলিক এপিআই বা না তা সন্ধান করার সহজ উপায়টি (এক্সকোডে) ফাংশনটির নাম টাইপ করা (যেমন objc_sync_enter()
; সি ফাংশনগুলির জন্য আর্গুমেন্ট নির্দিষ্ট করার দরকার নেই) , তারপরে কমান্ড-ক্লিক করার চেষ্টা করুন। যদি এটি আপনাকে সেই API এর শিরোনাম ফাইলটি দেখায়, তবে আপনি ভাল (যেহেতু আপনি শিরোনামটি সর্বজনীন না হলে আপনি দেখতে সক্ষম হবেন না) ।
@synchronized
অবজেক্টিভ-সি থেকে প্রাপ্ত নির্দেশিকার অ্যানালগটিতে সুইফটে একটি নির্বিচারে রিটার্ন টাইপ এবং দুর্দান্ত rethrows
আচরণ থাকতে পারে।
// Swift 3
func synchronized<T>(_ lock: AnyObject, _ body: () throws -> T) rethrows -> T {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return try body()
}
defer
বিবৃতিটির ব্যবহার অস্থায়ী ভেরিয়েবলের পরিচয় না দিয়ে সরাসরি কোনও মান ফেরত দেয়।
@noescape
আরও অপটিমাইজেশনের অনুমতি দিতে সুইফট 2- এ ক্লোজারে অ্যাট্রিবিউট যুক্ত করুন :
// Swift 2
func synchronized<T>(lock: AnyObject, @noescape _ body: () throws -> T) rethrows -> T {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return try body()
}
জিএনউইউসিসি [১] (যেখানে আমি নির্বিচারে রিটার্নের ধরণটি পছন্দ করি) এবং টড কানিংহাম [2] (যেখানে আমি পছন্দ করি defer
) এর উত্তরগুলির উপর ভিত্তি করে ।
সুইফট 4
সুইফ্ট 4-এ আপনি জিসিডি প্রেরণ সারিগুলি লক সংস্থানগুলিতে ব্যবহার করতে পারেন।
class MyObject {
private var internalState: Int = 0
private let internalQueue: DispatchQueue = DispatchQueue(label:"LockingQueue") // Serial by default
var state: Int {
get {
return internalQueue.sync { internalState }
}
set (newState) {
internalQueue.sync { internalState = newState }
}
}
}
.serial
অনুপলব্ধ বলে মনে হচ্ছে। তবে .concurrent
পাওয়া যায়। : /
myObject.state = myObject.state + 1
একই সাথে চালনা করেন তবে এটি মোট ক্রিয়াকলাপ গণনা করবে না বরং পরিবর্তে একটি অ-নিরপেক্ষবাদী মান অর্জন করবে। এই সমস্যাটি সমাধান করার জন্য, কলিং কোডটি সিরিয়াল কাতারে আবৃত করা উচিত যাতে পাঠানো এবং লেখার উভয়ই পরমাণুভাবে ঘটে। অবশ্যই ওবজ-সি এর @synchronised
একই সমস্যা রয়েছে, সুতরাং সেই অর্থে আপনার বাস্তবায়নটি সঠিক।
myObject.state += 1
একটি পঠন এবং তারপরে একটি রাইটিং অপারেশনের সংমিশ্রণ। কিছু অন্যান্য থ্রেড এখনও মান নির্ধারণ / লিখতে অভ্যন্তরে আসতে পারে। অনুযায়ী objc.io/blog/2018/12/18/atomic-variables , এটি চালানোর জন্য সহজ হবে set
পরিবর্তনশীল নিজেই অধীনে পরিবর্তে এবং একটি সিঙ্ক ব্লক / অবসান হবে।
রিটার্নের কার্যকারিতা যুক্ত করতে আপনি এটি করতে পারেন:
func synchronize<T>(lockObj: AnyObject!, closure: ()->T) -> T
{
objc_sync_enter(lockObj)
var retVal: T = closure()
objc_sync_exit(lockObj)
return retVal
}
পরবর্তীকালে, আপনি এটি ব্যবহার করে কল করতে পারেন:
func importantMethod(...) -> Bool {
return synchronize(self) {
if(feelLikeReturningTrue) { return true }
// do other things
if(feelLikeReturningTrueNow) { return true }
// more things
return whatIFeelLike ? true : false
}
}
ব্রায়ান ম্যাকলিমোর উত্তরটি ব্যবহার করে, আমি সুইট ২.০ ডিফার সক্ষমতার সাহায্যে সুরক্ষিত ম্যানর আটকানো অবজেক্টগুলিকে সমর্থন করার জন্য এটি বাড়িয়েছি।
func synchronized( lock:AnyObject, block:() throws -> Void ) rethrows
{
objc_sync_enter(lock)
defer {
objc_sync_exit(lock)
}
try block()
}
rethrows
নিক্ষেপণ বন্ধ (ব্যবহারের প্রয়োজন নেই try
) দিয়ে ব্যবহারকে সহজ করার জন্য ব্যবহার করা ভাল ।
সুইফট 3
এই কোডটিতে পুনরায় প্রবেশের ক্ষমতা রয়েছে এবং এটি অ্যাসিঙ্ক্রোনাস ফাংশন কলগুলির সাথে কাজ করতে পারে। এই কোডে, কিছুAsyncFunc () বলা হওয়ার পরে, সিরিয়াল কাতারে অন্য একটি ফাংশন বন্ধ হওয়ার প্রক্রিয়া শুরু হবে তবে সিগন্যাল () বলা না হওয়া অবধি semaphore.wait () দ্বারা অবরুদ্ধ করা হবে। অভ্যন্তরীণ কিউ.সেনসি ব্যবহার করা উচিত নয় কারণ এটি ভুল না হলে এটি মূল থ্রেডটিকে ব্লক করে দেবে।
let internalQueue = DispatchQueue(label: "serialQueue")
let semaphore = DispatchSemaphore(value: 1)
internalQueue.async {
self.semaphore.wait()
// Critical section
someAsyncFunc() {
// Do some work here
self.semaphore.signal()
}
}
mistc_sync_enter / objc_sync_exit ত্রুটি পরিচালনা করা ছাড়া ভাল ধারণা নয়।
2018 ডাব্লুডাব্লুডিসির "ক্র্যাশগুলি এবং ক্র্যাশ লগগুলি বোঝার" সেশনে 414 তারা সিঙ্কের সাথে ডিসপ্যাচকিউগুলি ব্যবহার করে নিম্নলিখিত পদ্ধতিটি দেখায়।
সুইফ্ট 4 এ নিম্নলিখিতগুলির মতো কিছু হওয়া উচিত:
class ImageCache {
private let queue = DispatchQueue(label: "sync queue")
private var storage: [String: UIImage] = [:]
public subscript(key: String) -> UIImage? {
get {
return queue.sync {
return storage[key]
}
}
set {
queue.sync {
storage[key] = newValue
}
}
}
}
যাইহোক আপনি বাধা সহ সমবর্তী সারি ব্যবহার করে দ্রুত পাঠগুলিও তৈরি করতে পারেন। সিঙ্ক এবং অ্যাসিঙ্ক রিডগুলি একই সাথে সঞ্চালিত হয় এবং একটি নতুন মান লেখা পূর্ববর্তী ক্রিয়াকলাপ সমাপ্ত হওয়ার জন্য অপেক্ষা করে।
class ImageCache {
private let queue = DispatchQueue(label: "with barriers", attributes: .concurrent)
private var storage: [String: UIImage] = [:]
func get(_ key: String) -> UIImage? {
return queue.sync { [weak self] in
guard let self = self else { return nil }
return self.storage[key]
}
}
func set(_ image: UIImage, for key: String) {
queue.async(flags: .barrier) { [weak self] in
guard let self = self else { return }
self.storage[key] = image
}
}
}
সুইফট 4 এ এনএসলক ব্যবহার করুন :
let lock = NSLock()
lock.lock()
if isRunning == true {
print("Service IS running ==> please wait")
return
} else {
print("Service not running")
}
isRunning = true
lock.unlock()
সতর্কতা এনএসলক শ্রেণিটির লকিং আচরণটি বাস্তবায়নের জন্য পসিক্স থ্রেড ব্যবহার করে। কোনও এনএসলক অবজেক্টে আনলক বার্তা প্রেরণ করার সময় আপনাকে অবশ্যই নিশ্চিত হওয়া উচিত যে বার্তাটি একই থ্রেড থেকে প্রেরণ করা হয়েছিল যা প্রাথমিক লক বার্তা প্রেরণ করেছে। কোনও আলাদা থ্রেড থেকে লক আনলক করা অনির্ধারিত আচরণের ফলস্বরূপ।
আধুনিক সুইফট 5 এ, রিটার্ন সক্ষমতার সাথে:
/**
Makes sure no other thread reenters the closure before the one running has not returned
*/
@discardableResult
public func synchronized<T>(_ lock: AnyObject, closure:() -> T) -> T {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return closure()
}
রিটার্ন মান সক্ষমতা সদ্ব্যবহার করতে এটি এটিকে ব্যবহার করুন:
let returnedValue = synchronized(self) {
// Your code here
return yourCode()
}
বা অন্যথায় যে মত:
synchronized(self) {
// Your code here
yourCode()
}
GCD
)। এটি মূলত বলে মনে হয় Noone ব্যবহারসমূহ বা কিভাবে ব্যবহার করতে বুঝতে পারে Thread
। আমি এতে সন্তুষ্ট - যদিও GCD
গটকা এবং সীমাবদ্ধতায় ভরা।
চেষ্টা করুন: এনএসরেকারসিভলক
একটি লক যা কোনও অচলাবস্থার কারণ ছাড়াই একই থ্রেড দ্বারা একাধিকবার অধিগ্রহণ করা যেতে পারে।
let lock = NSRecursiveLock()
func f() {
lock.lock()
//Your Code
lock.unlock()
}
func f2() {
lock.lock()
defer {
lock.unlock()
}
//Your Code
}
চিত্র আমি আমার সুইফট 5 বাস্তবায়ন পোস্ট করব, পূর্বের উত্তরগুলির তুলনায় তৈরি। ধন্যবাদ বন্ধুরা! আমি এটির সাথে একটি মানও ফিরিয়ে দেওয়া সহায়ক বলে মনে করেছি, সুতরাং আমার কাছে দুটি পদ্ধতি রয়েছে।
এখানে প্রথম তৈরি করার জন্য একটি সাধারণ বর্গ:
import Foundation
class Sync {
public class func synced(_ lock: Any, closure: () -> ()) {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
closure()
}
public class func syncedReturn(_ lock: Any, closure: () -> (Any?)) -> Any? {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return closure()
}
}
তারপরে যদি কোনও ফেরতের মান প্রয়োজন হয় তবে এটি এর মতো ব্যবহার করুন:
return Sync.syncedReturn(self, closure: {
// some code here
return "hello world"
})
বা:
Sync.synced(self, closure: {
// do some work synchronously
})
public class func synced<T>(_ lock: Any, closure: () -> T)
, অকার্যকর এবং অন্য কোনও ধরণের উভয়ের জন্যই কাজ করে। রেগ্রোস স্টাফও রয়েছে।
xCode 8.3.1, দ্রুত 3.1
বিভিন্ন থ্রেড (async) থেকে লেখার মান পড়ুন।
class AsyncObject<T>:CustomStringConvertible {
private var _value: T
public private(set) var dispatchQueueName: String
let dispatchQueue: DispatchQueue
init (value: T, dispatchQueueName: String) {
_value = value
self.dispatchQueueName = dispatchQueueName
dispatchQueue = DispatchQueue(label: dispatchQueueName)
}
func setValue(with closure: @escaping (_ currentValue: T)->(T) ) {
dispatchQueue.sync { [weak self] in
if let _self = self {
_self._value = closure(_self._value)
}
}
}
func getValue(with closure: @escaping (_ currentValue: T)->() ) {
dispatchQueue.sync { [weak self] in
if let _self = self {
closure(_self._value)
}
}
}
var value: T {
get {
return dispatchQueue.sync { _value }
}
set (newValue) {
dispatchQueue.sync { _value = newValue }
}
}
var description: String {
return "\(_value)"
}
}
print("Single read/write action")
// Use it when when you need to make single action
let obj = AsyncObject<Int>(value: 0, dispatchQueueName: "Dispatch0")
obj.value = 100
let x = obj.value
print(x)
print("Write action in block")
// Use it when when you need to make many action
obj.setValue{ (current) -> (Int) in
let newValue = current*2
print("previous: \(current), new: \(newValue)")
return newValue
}
এক্সটেনশন ডিসপ্যাচগ্রুপ
extension DispatchGroup {
class func loop(repeatNumber: Int, action: @escaping (_ index: Int)->(), completion: @escaping ()->()) {
let group = DispatchGroup()
for index in 0...repeatNumber {
group.enter()
DispatchQueue.global(qos: .utility).async {
action(index)
group.leave()
}
}
group.notify(queue: DispatchQueue.global(qos: .userInitiated)) {
completion()
}
}
}
ক্লাস ভিউ কন্ট্রোলার
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//sample1()
sample2()
}
func sample1() {
print("=================================================\nsample with variable")
let obj = AsyncObject<Int>(value: 0, dispatchQueueName: "Dispatch1")
DispatchGroup.loop(repeatNumber: 5, action: { index in
obj.value = index
}) {
print("\(obj.value)")
}
}
func sample2() {
print("\n=================================================\nsample with array")
let arr = AsyncObject<[Int]>(value: [], dispatchQueueName: "Dispatch2")
DispatchGroup.loop(repeatNumber: 15, action: { index in
arr.setValue{ (current) -> ([Int]) in
var array = current
array.append(index*index)
print("index: \(index), value \(array[array.count-1])")
return array
}
}) {
print("\(arr.value)")
}
}
}
সুইফটের সম্পত্তি র্যাপারগুলির সাথে, আমি এখন এটি ব্যবহার করছি:
@propertyWrapper public struct NCCSerialized<Wrapped> {
private let queue = DispatchQueue(label: "com.nuclearcyborg.NCCSerialized_\(UUID().uuidString)")
private var _wrappedValue: Wrapped
public var wrappedValue: Wrapped {
get { queue.sync { _wrappedValue } }
set { queue.sync { _wrappedValue = newValue } }
}
public init(wrappedValue: Wrapped) {
self._wrappedValue = wrappedValue
}
}
তারপরে আপনি ঠিক করতে পারেন:
@NCCSerialized var foo: Int = 10
অথবা
@NCCSerialized var myData: [SomeStruct] = []
তারপরে আপনি যেমনটি চান তেমন চলক অ্যাক্সেস করুন।
DispatchQueue
ব্যবহারকারীর কাছ থেকে লুকানো রয়েছে তা তৈরি করার পার্শ্ব প্রতিক্রিয়া রয়েছে । আমি আমার মনকে নিশ্চিন্ত করার জন্য এই এসও রেফারেন্সটি পেয়েছি: stackoverflow.com/a/35022486/1060314
উপসংহারে, এখানে আরও সাধারণ উপায় দিন যা রিটার্ন মান বা অকার্যকর, এবং নিক্ষেপ অন্তর্ভুক্ত
import Foundation
extension NSObject {
func synchronized<T>(lockObj: AnyObject!, closure: () throws -> T) rethrows -> T
{
objc_sync_enter(lockObj)
defer {
objc_sync_exit(lockObj)
}
return try closure()
}
}
লকগুলি দিয়ে কেন এটি কঠিন এবং ঝামেলা সৃষ্টি করে? ডিসপ্যাচ বাধা ব্যবহার করুন।
একটি প্রেরণ বাধা একটি সমবর্তী সারির মধ্যে একটি সিঙ্ক্রোনাইজেশন পয়েন্ট তৈরি করে।
এটি চলমান অবস্থায়, সারিবদ্ধ অন্য কোনও ব্লক চালানোর অনুমতি নেই, এটি সমবর্তী এবং অন্যান্য কোরগুলি উপলভ্য থাকলেও।
যদি এটি একচেটিয়া (লিখন) লকের মতো মনে হয় তবে তা। অ-বাধা ব্লকগুলি ভাগ করা (পঠিত) লক হিসাবে ভাবা যেতে পারে।
যতক্ষণ সম্পদের সমস্ত অ্যাক্সেস সারির মাধ্যমে সঞ্চালিত হয়, বাধাগুলি খুব সস্তা সিঙ্ক্রোনাইজেশন সরবরাহ করে।
আইওরোবারির উপর ভিত্তি করে একটি উপ-শ্রেণীর কেস পরীক্ষা করুন
class Foo: NSObject {
func test() {
print("1")
objc_sync_enter(self)
defer {
objc_sync_exit(self)
print("3")
}
print("2")
}
}
class Foo2: Foo {
override func test() {
super.test()
print("11")
objc_sync_enter(self)
defer {
print("33")
objc_sync_exit(self)
}
print("22")
}
}
let test = Foo2()
test.test()
1
2
3
11
22
33
আরেকটি পদ্ধতি হ'ল একটি সুপারক্লাস তৈরি করা এবং তারপরে এটি উত্তরাধিকারী। এইভাবে আপনি আরও সরাসরি জিসিডি ব্যবহার করতে পারেন
class Lockable {
let lockableQ:dispatch_queue_t
init() {
lockableQ = dispatch_queue_create("com.blah.blah.\(self.dynamicType)", DISPATCH_QUEUE_SERIAL)
}
func lock(closure: () -> ()) {
dispatch_sync(lockableQ, closure)
}
}
class Foo: Lockable {
func boo() {
lock {
....... do something
}
}