poo - ¿Por qué Java y C#agregaron bloqueo intrínseco a cada objeto?
c# que capture los datos de un empleado utilizando poo (4)
Agrega un costo adicional por cada objeto creado, aunque en realidad solo lo usará en una pequeña fracción de los objetos.
Eso está determinado por la implementación de JVM. La especificación de JVM dice: "La asociación de un monitor con un objeto se puede gestionar de varias maneras que están fuera del alcance de esta especificación. Por ejemplo, el monitor se puede asignar y desasignar al mismo tiempo que el objeto. Alternativamente, puede asignarse dinámicamente en el momento en que un subproceso intenta obtener acceso exclusivo al objeto y liberarse en algún momento posterior cuando no haya ningún subproceso en el monitor para el objeto ".
Todavía no he visto mucho código fuente de JVM, pero me sorprendería mucho si alguno de los JVM comunes manejara esto de manera ineficiente.
El uso del bloqueo se vuelve implícito, tener lockMap.get (clave) .lock () es más legible que la sincronización en objetos arbitrarios, por ejemplo, sincronizar (clave) {...}.
Estoy en completo desacuerdo. Una vez que sepa el significado de synchronize
, es mucho más legible que una cadena de llamadas a métodos.
Los métodos sincronizados pueden causar un error sutil de usuarios que bloquean el objeto con los métodos sincronizados
Es por eso que necesitas saber el significado de synchronize
. Si lees acerca de lo que hace, entonces evitar estos errores se vuelve bastante trivial. Regla de oro: no use el mismo bloqueo en varios lugares a menos que esos lugares necesiten compartir el mismo bloqueo. Lo mismo podría decirse de la estrategia de bloqueo / exclusión de cualquier idioma.
Puede estar seguro de que cuando pasa un objeto a una tercera API de partición, no se está utilizando el bloqueo.
Derecha. Eso suele ser algo bueno. Si está bloqueado, debería haber una buena razón por la que está bloqueado. Otros hilos (de terceros o no) deben esperar sus turnos.
Si sincronizas en myObject
con la intención de permitir que otros subprocesos utilicen myObject
al mismo tiempo, lo estás haciendo mal. Podrías sincronizar fácilmente el mismo bloque de código usando myOtherObject
si eso ayudara.
Sin mencionar la contaminación del espacio de nombres para todos y cada uno de los objetos (en C # al menos los métodos son estáticos, en Java las primitivas de sincronización tienen que usar esperar, no sobrecargar la espera en Objeto ...)
La clase Object
incluye algunos métodos convenientes relacionados con la sincronización, a saber, notify()
, notifyAll()
y wait()
. El hecho de que no hayas necesitado usarlos no significa que no sean útiles. Podrías quejarte fácilmente de clone()
, equals()
, toString()
, etc.
Hacer que cada objeto se pueda bloquear parece un error de diseño:
- Agrega un costo adicional por cada objeto creado, aunque en realidad solo lo usará en una pequeña fracción de los objetos.
- El uso del bloqueo se vuelve implícito, tener
lockMap.get(key).lock()
es más legible que la sincronización en objetos arbitrarios, por ejemplo,synchronize (key) {...}
. - Los métodos sincronizados pueden causar un error sutil de usuarios que bloquean el objeto con los métodos sincronizados
- Puede estar seguro de que cuando pasa un objeto a una tercera API de partición, no se está utilizando el bloqueo.
p.ej
class Syncer {
synchronized void foo(){}
}
...
Syncer s = new Syncer();
synchronize(s) {
...
}
// in another thread
s.foo() // oops, waiting for previous section, deadlocks potential
- Sin mencionar la contaminación del espacio de nombres para todos y cada uno de los objetos (en C # al menos los métodos son estáticos, en Java las primitivas de sincronización tienen que usar
await
, no sobrecargar lawait
enObject
...)
Sin embargo, estoy seguro de que hay alguna razón para este diseño. ¿Cuál es el gran beneficio de las cerraduras intrínsecas?
En realidad solo tienes referencia a ese monitor en cada objeto; el objeto de monitor real se crea solo cuando se usa la sincronización => no se pierde tanta memoria.
La alternativa sería agregar el monitoreo manual a las clases que necesita; Esto complicaría mucho el código y sería más propenso a errores. Java ha cambiado el rendimiento por productividad.
Supongo que como toString (), los diseñadores pensaron que los beneficios superaban los costos.
Se tuvieron que tomar muchas decisiones y muchos de los conceptos no se probaron (¡se verificaron excepciones!), Pero en general estoy seguro de que es bastante gratuito y más útil que un objeto de "Bloqueo" explícito.
¿También agrega un objeto "Bloquear" al idioma o la biblioteca? Parece una construcción de lenguaje, pero los objetos en la biblioteca muy raramente (¿alguna vez?) Tienen un tratamiento especial, pero tratar el subprocesamiento más como una construcción de biblioteca podría haber ralentizado las cosas ...
Un beneficio es el desbloqueo automático al salir del bloque synchronized
, incluso por excepción.