Meu aplicativo usa uma classe A
e suas subclasses SubA_x
.
A
possui uma propriedade estática serialNumber
que só é modificada pela classe A
quando uma subclasse é inicializada. Ele define uma propriedade let name
para que cada subclasse tenha um nome exclusivo. Aqui está o código:
class A {
static var serialNumber = 0
let name: String
init( /* some parameters */ ) {
A.serialNumber += 1
self.name = "\(A.serialNumber)"
}
}
final class SubA_1: A {
init( /* some parameters */ ) {
super.init( /* some parameters */ )
}
}
Com a verificação estrita de simultaneidade do Swift 6, a linha onde serialNumber
é inicializada fornece o erro
A propriedade estática 'serialNumber' não é segura para simultaneidade porque é um estado mutável compartilhado global não isolado
Entendo que cada subclasse A
pode ser modificada var serialNumber
em qualquer thread, portanto, corridas de dados são possíveis.
Mas como consigo essa funcionalidade de maneira segura para a simultaneidade?
Tentei fornecer serialNumber
por um ator:
actor SerialNumberManager {
private var serialNumber = 0
func getNextSerialNumber() -> Int {
serialNumber += 1
return serialNumber
}
}
mas não consigo ligar getNextSerialNumber()
, init
exceto quando init
é assíncrono. Mas então posso inicializar uma subclasse apenas em um contexto assíncrono, etc.
Provavelmente eu poderia fornecer minha própria sincronização baseada em GCD, mas deveria haver uma maneira de fazer isso dentro da simultaneidade do Swift.
Se você deseja um estado compartilhado e seguro para threads,
actor
é uma abordagem lógica. Porém, se você quiser um que possa ser invocado a partir de contextos síncronos, basta escrever seu próprio gerenciador, implementando sua própria sincronização manual (com fila serial GCD ou, como mostrado abaixo, com um bloqueio):Observe que só usaríamos
@unchecked Sendable
quando implementássemos a sincronização manual, como acima.E você poderia usá-lo assim:
Alternativamente, você poderia usar um
OSAllocatedUnfairLock
, que já éSendable
:Por uma questão de integridade, outras alternativas incluem atômicos ou UUIDs .