Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

172
Vistas
Xcode informa incorrectamente la condición de carrera de acceso rápido

Creo que XCode informa incorrectamente Swift Access Race en mi SynchronizedDictionary , ¿o no?

Mi SynchronizedDictionary se ve así:

 public struct SynchronizedDictionary<K: Hashable, V> { private var dictionary = [K: V]() private let queue = DispatchQueue( label: "SynchronizedDictionary", qos: DispatchQoS.userInitiated, attributes: [DispatchQueue.Attributes.concurrent] ) public subscript(key: K) -> V? { get { return queue.sync { return self.dictionary[key] } } mutating set { queue.sync(flags: .barrier) { self.dictionary[key] = newValue } } } }

El siguiente código de prueba activará un problema de "Carrera de acceso rápido" (cuando Thread Sanitizer esté activado para el esquema):

 var syncDict = SynchronizedDictionary<String, String>() let setExpectation = XCTestExpectation(description: "set_expectation") let getExpectation = XCTestExpectation(description: "get_expectation") let queue = DispatchQueue(label: "SyncDictTest", qos: .background, attributes: [.concurrent]) queue.async { for i in 0...100 { syncDict["\(i)"] = "\(i)" } setExpectation.fulfill() } queue.async { for i in 0...100 { _ = syncDict["\(i)"] } getExpectation.fulfill() } self.wait(for: [setExpectation, getExpectation], timeout: 30)

El Swift Race Access se ve así:

Acceso rápido a la carrera Realmente no esperaba que hubiera una condición de carrera de acceso aquí, porque SynchronizedDictionary debería manejar la concurrencia.

Puedo solucionar el problema, en la prueba, envolviendo la obtención y configuración en un DispatchQueue similar a la implementación real de SynchronizedDictionary :

 let accessQueue = DispatchQueue( label: "AccessQueue", qos: DispatchQoS.userInitiated, attributes: [DispatchQueue.Attributes.concurrent] ) var syncDict = SynchronizedDictionary<String, String>() let setExpectation = XCTestExpectation(description: "set_expectation") let getExpectation = XCTestExpectation(description: "get_expectation") let queue = DispatchQueue(label: "SyncDictTest", qos: .background, attributes: [.concurrent]) queue.async { for i in 0...100 { accessQueue.sync(flags: .barrier) { syncDict["\(i)"] = "\(i)" } } setExpectation.fulfill() } queue.async { for i in 0...100 { accessQueue.sync { _ = syncDict["\(i)"] } } getExpectation.fulfill() } self.wait(for: [setExpectation, getExpectation], timeout: 30)

... pero eso ya sucede dentro de SynchronizedDictionary , entonces, ¿por qué Xcode informa una condición de carrera de acceso? - ¿Xcode tiene la culpa o me estoy perdiendo algo?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

El desinfectante de subprocesos informa una carrera de acceso Swift al

 var syncDict = SynchronizedDictionary<String, String>()

estructura, porque hay un acceso mutante (a través del setter subíndice) en

 syncDict["\(i)"] = "\(i)"

de un subproceso, y un acceso de solo lectura a la misma estructura (a través del captador de subíndices) en

 _ = syncDict["\(i)"]

de un hilo diferente, sin sincronización.

Esto no tiene nada que ver con el acceso en conflicto a la propiedad private var dictionary , o con lo que sucede dentro de los métodos de subíndice. Obtendrá la misma "carrera de acceso rápido" si simplifica la estructura para

 public struct SynchronizedDictionary<K: Hashable, V> { private let dummy = 1 public subscript(key: String) -> String { get { return key } set { } } }

Entonces, este es un informe correcto del desinfectante de hilos, no un error.

Una posible solución sería definir una clase en su lugar:

 public class SynchronizedDictionary<K: Hashable, V> { ... }

Ese es un tipo de referencia y el setter de subíndice ya no muta la variable syncDict (que ahora es un "puntero" en el almacenamiento de objetos real). Con ese cambio, su código se ejecuta sin errores.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda