¿Cómo funciona el enhebrado en Ruby 2.0 y cómo es diferente de Ruby 1.9.2?

True Thread Variables locales:

A partir de Ruby 1.9.2 Hilo # [], # [] =, #keys y #key? obtendría / establecería variables locales de fibra, ahora Thread obtiene las #thread_variables, #thread_variable ?, métodos # thread_variable_get, #thread_variable_set como equivalentes que son thread local

Fibra local:

  b = nulo 
   a = Fiber.new do 
       Thread.current [: foo] = 1 
       b.transferencia 
       Hilo.corriente [: foo] 
   fin 
   b = Fiber.new do 
       Thread.current [: foo] = 2 
       Una transferencia 
   fin 
   pone a.resume # => 1

Hilo local:

  b = nulo 
   a = Fiber.new do 
     Thread.current [: foo] = 1 
     b.transferencia 
     Hilo.corriente [: foo] 
   fin 
   b = Fiber.new do 
     Thread.current [: foo] = 2 
     Una transferencia 
   fin 
   pone a.resume # => 2

Manejo de interrupción de subproceso asíncrono:

En Ruby los hilos pueden ser eliminados o una excepción puede ser provocada por otro. Esta no es una característica terriblemente segura, ya que el hilo de matar no sabe qué está ejecutando el hilo que se está matando, puede suceder que esté matando un hilo en medio de una asignación de recursos importante o desasignación. Ahora tenemos una función para lidiar con esto de manera más segura.
Por ejemplo, la biblioteca stdlib timeout funciona generando un segundo subproceso, que espera la cantidad de tiempo especificada, y luego genera una excepción en el subproceso original.
Supongamos que teníamos una biblioteca de agrupación de conexiones que podría hacer frente a usted si no vuelve a verificar una conexión, pero fallaría si se interrumpiera la salida o la conexión. Está escribiendo un método para obtener una conexión, hacer una solicitud y luego devolverla, y sospecha que los usuarios de este método pueden cerrarlo en un tiempo de espera.

  solicitud de definición (detalles) 
   resultado = nulo
 
       # El bloque diferirá las excepciones dadas si se generan en este hilo por 
       # otro hilo hasta el final del bloque.  Las excepciones no se rescatan o 
       # ignorado, pero manejado más tarde.

       Thread.handle_interrupt (Timeout :: ExitException =>: never) do 

         # no hay peligro de que el tiempo de espera interrumpa el pago 

         connection = connection_pool.checkout 


         # si el proceso de pago tardó demasiado, maneje la interrupción de inmediato, de manera efectiva 
         # planteando la excepción pendiente aquí 

         if Thread.pending_interrupt? 
             Thread.handle_interrupt (Tiempo de espera :: ExitException =>: inmediato) 
         fin 

         # permitir interrupciones durante IO (o llamada de extensión C)

         Thread.handle_interrupt (Timeout :: ExitException =>: on_blocking) hacer 
             result = connection.request (detalles) 
         fin 

         # no hay peligro de tiempo de espera que interrumpa el registro

     connection_pool.checkin (conexión) 
     fin 
 fin

Este método se puede envolver de forma segura en un tiempo de espera, y la conexión siempre se desprotegerá por completo, y si completa la solicitud, siempre se completará el registro. Si el tiempo de espera ocurre durante el registro, no interrumpirá el registro, pero seguirá apareciendo al final del método.

Este es un ejemplo ligeramente inventado, pero cubre los puntos principales de esta gran característica nueva.

Mejor error al unirse al hilo actual / principal:

Si intenta llamar a #join o #value en el subproceso actual o principal, ahora se genera un ThreadError, que hereda de StandardError, en lugar de ‘fatal’ que hereda de Exception.

  empezar 
       Thread.current.joinrescue => ee # => #  
   fin

Cambios de mutex
No puedo pensar en un ejemplo particularmente interesante para esto, pero ahora puede verificar si el hilo actual posee un mutex.

  requiere "hilo" 
   lock = Mutex.new 
   cerradura 
   cerradura  # => verdadero 
   Thread.new {lock.owned?}. Value # => false

También afectando a Mutex, los métodos que cambian el estado del mutex ya no están permitidos en los manejadores de señales: #lock, # unlock, # try_lock, #synchronize y #sleep.

Y aparentemente #sleep puede levantarse temprano, por lo que deberá verificar que haya transcurrido la cantidad de tiempo correcta si los tiempos precisos son importantes.

  sleep_time = 0.1 
   inicio = tiempo.ahora 
   lock.sleep (sleep_time) 
   transcurrido = Time.now - inicio 
   lock.sleep (sleep_time - transcurrido) si transcurrió <sleep_time