Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

476
Visualizações
What is the reason behind objc_sync_enter doesn't work well with struct, but works well with class?

I have the following demo code.

struct IdGenerator {
    private var lastId: Int64
    private var set: Set<Int64> = []
    
    init() {
        self.lastId = 0
    }
    
    mutating func nextId() -> Int64 {
        objc_sync_enter(self)
        defer {
            objc_sync_exit(self)
        }
        
        repeat {
            lastId = lastId + 1
        } while set.contains(lastId)

        precondition(lastId > 0)
        
        let (inserted, _) = set.insert(lastId)
        precondition(inserted)
        
        return lastId
    }
}

var idGenerator = IdGenerator()

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func click(_ sender: Any) {
        DispatchQueue.global(qos: .userInitiated).async {
            for i in 1...10000 {
                let id = idGenerator.nextId()
                print("i : \(id)")
            }
        }

        DispatchQueue.global(qos: .userInitiated).async {
            for j in 1...10000 {
                let id = idGenerator.nextId()
                print("j : \(id)")
            }
        }
    }
}

Whenever I execute click, I would get the following crash

Thread 5 Queue : com.apple.root.user-initiated-qos (concurrent)
#0  0x000000018f58b434 in _NativeSet.insertNew(_:at:isUnique:) ()
#1  0x000000018f598d10 in Set._Variant.insert(_:) ()
#2  0x00000001001fe31c in IdGenerator.nextId() at /Users/yccheok/Desktop/xxxx/xxxx/ViewController.swift:30
#3  0x00000001001fed8c in closure #2 in ViewController.click(_:) at /Users/yccheok/Desktop/xxxx/xxxx/ViewController.swift:56

It isn't clear why the crash happen. My raw guess is, under struct, objc_sync_enter(self) doesn't work as expected. 2 threads accessing Set simultaneously will cause such an issue.


If I change the struct to class, everything just work fine.

class IdGenerator {
    private var lastId: Int64
    private var set: Set<Int64> = []
    
    init() {
        self.lastId = 0
    }
    
    func nextId() -> Int64 {
        objc_sync_enter(self)
        defer {
            objc_sync_exit(self)
        }
        
        repeat {
            lastId = lastId + 1
        } while set.contains(lastId)

        precondition(lastId > 0)
        
        let (inserted, _) = set.insert(lastId)
        precondition(inserted)
        
        return lastId
    }
}

May I know what is the reason behind? Why the above objc_sync_enter works well in class, but not in struct?

over 4 years ago · Santiago Trujillo
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda