Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Ruby3 multithreaded parallel Ractor

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly introduces the Ruby3 multithreading parallel Ractor how to use the relevant knowledge, the content is detailed and easy to understand, the operation is simple and fast, has a certain reference value, I believe that everyone after reading this Ruby3 multithreading parallel Ractor how to use the article will have a harvest, let's take a look.

Before Ruby3, Thread was used to create new threads, but multithreads created in this way are concurrent rather than parallel. MRI has a global interpreter lock GIL to control that only one thread is executing at a time:

# main Threadt1 = Thread.new do # new Thread sleep 3endt1.join

Ruby3 supports true multithreaded parallelism through Ractor (the Ruby Actor,Actor model modifies state through message passing), and multiple Ractor can run independently in parallel.

# main Ractor# create a Ractorr = Ractor.new do sleep 2 Ractor.yield "hello" endputs r.take that can run in parallel with main Ractor

Note that there is at least one native Ractor thread in each Ractor, but there is a separate Ruby thread inside each Ruby, so that there can be at most one thread running inside the Ractor at a time. From this point of view, Ractor is actually an interpreter thread, and each interpreter thread has a global interpreter lock.

If main Ractor exits, other Ractor will also receive an exit signal, just as when main Thread exits, other Thread will also exit.

Create Ractor

Create an instance of Ractor using Ractor.new. When you create an instance, you specify a block of statements in which the code runs in the Ractor.

R = Ractor.new do puts "new Ractor" end

You can specify a name for the Ractor instance on the parameters of the new method:

R = Ractor.new (name: "ractor1") do puts "new Ractor" endputs r.name # ractor1

The new method can also specify other parameters, which must precede the name parameter, and are passed directly to the statement block parameter as is:

Arr = [11,22,33] r = Ractor.new (arr, name: "R1") do | arr | puts "arr" endsleep 1

The parameters of new will be explained later.

You can use Ractor.current to get the current Ractor instance and Ractor.count to get the number of Ractor instances currently alive.

Passing messages between Ractor

Ractor delivers messages in two ways:

Push method: push messages to a specific Ractor instance, using r.send (Msg) or alias r 'ok'# is basically equivalent to r = Ractor.new do msg = Ractor.receive msgendr.send' ok'r.take # = > 'ok' message port

When messages are passed between Ractor, they are actually delivered through the message port of Ractor.

Each Ractor has its own incoming port and outgoing port:

Incoming port: the port on which the Ractor receives messages, which is used by r.send and Ractor.receive

Each incoming port is connected to a queue of unlimited size

All incoming messages from r.send are written to the queue, and because the size of the queue is unlimited, r.send never blocks

Ractor.receive pops up a message from the queue, and when the queue is empty, Ractor.receive is blocked until a new message appears

You can use r.close_incoming to shut down incoming port. After closing the port, r.send will report an error directly. Ractor.receive will first take data from the queue, and then call Ractor.receive to report an error when the queue is empty.

Outgoing port: the port on which messages are outgoing from the Ractor, which is used by Ractor.yield and r.take

When the Ractor.yield or Ractor statement block returns, the message flows out of outgoing port

When there is no r.take to receive messages, the Ractor.yield inside r will be blocked

When there is no Ractor.yield inside r, r.take will be blocked

Ractor.yield messages from outgoing port can be waited by any number of r.take, but only one r.take can get the message

You can use r.close_outgoing to shut down outgoing port. After closing the port, calling r.take and Ractor.yield will report an error directly. If the r.take is blocking (waiting for a Ractor.yield message), closing the outgoing port operation will cancel all waiting take and report an error

Ractor.select waits for messages

You can use Ractor.select (R1 ~ R2 ~ R3...) Wait for a message on one or more Ractor instances outgoing port (therefore, select is mainly used to wait for a message from Ractor.yield) and return immediately after waiting for the first message.

The return value of Ractor.select is in the format [r, obj], where:

R represents the Ractor instance that is waiting

Obj represents the received message object

For example:

R1 = Ractor.new {'R1'} R2 = Ractor.new {'R2'} rs = [R1, R2] as = [] # Wait for R1 or R2 Ractor.yieldr, obj = Ractor.select (* rs) rs.delete (r) as

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report