DEV Community

GoyesDev
GoyesDev

Posted on

[SC] @unchecked Sendable

Preguntas

¿Qué significa exactamente @unchecked Sendable y en qué se diferencia de Sendable normal?

@unchecked Sendable significa que un tipo de dato específico conforma el contrato Sendable pero, a pesar de que el compilador podría no ser capaz de garantizar las condiciones del contrato, el desarrollador remueve esa validación y él se compromete a sincronizar el acceso a datos.

¿En qué situaciones es apropiado usar @unchecked Sendable?

Se puede usar @unchecked Sendable si el código ha demostrado ser seguro en un ambiente concurrente y se usa como solución temporal/intermedia hasta que se migre a un actor.

El acceso a datos debe controlarse internamente con un lock.

¿Qué riesgos concretos introduce el uso de @unchecked Sendable?

Puede ser que el día que se agregue @unchecked Sendable a una clase esta en realidad sea segura para usar en un ambiente concurrente. Sin embargo, no hay certeza de que el día de mañana alguien agregue una funcionalidad a la clase y haya pasado por alto la sincronización de los hilos para acceder a los datos.

Por ejemplo, considerar la clase:

nonisolated final class ArticleTitlesCache: @unchecked Sendable {
  private let cacheMutatingLock = DispatchQueue(label: "cache.lock.queue")

  private var articleTitles: Set<String> = []

  func addArticleTitle(_ title: String) {
    cacheMutatingLock.sync {
      _ = articleTitles.insert(title)
    }
  }

  func cachedArticleTitles() -> Set<String> {
    return cacheMutatingLock.sync {
      return articleTitles
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

El día de mañana, se quiere agregar una funcionalidad para contar el número de artículos almacenados que, idealmente, se construiría así:

Alguien el día de mañana podría olvidar envolver con cacheMutatingLock la nueva funcionalidad:

var count: Int {
  cacheMutatingLock.sync {
    articleTitles.count
  }
}
Enter fullscreen mode Exit fullscreen mode

Sin embargo, se pasó por alto la sincronización de los hilos y se escribió así:

var count: Int {
  articleTitles.count
}
Enter fullscreen mode Exit fullscreen mode

¿Por qué el compilador no puede verificar la seguridad de hilos cuando se usa un DispatchQueue como lock?

El compilador verifica que una implementación sea segura en términos de concurrencia de forma estructural y estática que implica el uso de valores inmutables, tipos de datos Sendable, y sincronización de hilos por medio de dominios de aislamiento y async/await.

Usar DispatchQueue correctamente para sincronizar hilos requiere una convención de comportamiento en tiempo de ejecución - El día de mañana un desarrollador puede olvidar sincronizar los hilos con DispatchQueue y el comportamiento se daña.

¿Cuál es la alternativa recomendada a @unchecked Sendable y por qué es superior?

Se recomienda usar Sendable (sin @unchecked).

Recitación

¿Puedes explicar con tus propias palabras qué ocurre si se accede a articleTitles sin pasar por cacheMutatingLock?

Puede ocurrir una carrera de datos.

¿Qué ventaja ofrece usar un actor frente a un lock manual?

El actor le da al compilador una garantía estructural: sabe por diseño que todo acceso a su estado está serializado.

Repaso

¿En qué escenario específico el artículo acepta @unchecked Sendable como solución válida, y qué condición impone para usarlo?

Es válido poner @unchecked Sendable es una clase que se sabe que es segura para usar en ambientes concurrentes (lo ha sido por mucho tiempo) y se programa una migración para convertirla en actor (con un ticket, por ejemplo).

Si tuvieras que migrar ArticleTitlesCache a un actor, ¿qué cambios estructurales serían necesarios?

Se elimina la sincronización con DispatchQueue y todos los llamados de los clientes tendrían que cambiar para usar await.


Bibliografía

Top comments (0)