Multithreaded%20Applications - PowerPoint PPT Presentation

About This Presentation
Title:

Multithreaded%20Applications

Description:

use Thread; use Chatbot::Eliza::Server; use constant PORT = 12000; ... tells perl to look in Charbot::Eliza. if it can't find a method, botprompt ... – PowerPoint PPT presentation

Number of Views:29
Avg rating:3.0/5.0
Slides: 27
Provided by: Andr839
Category:

less

Transcript and Presenter's Notes

Title: Multithreaded%20Applications


1
Chapter 11
  • Multithreaded Applications

2
About threads
  • Instead of two processes with individual memory,
    signal handlers, global variables, a
    multithreaded program is a single process
    sharing
  • global variables,
  • filehandles,
  • signal handlers,
  • other resources.
  • Much easier to share resources but also much more
    likely, the possibility of contention.
  • Solution resource locking.

3
Thread API
  • Described in Thread, ThreadQueue,
    ThreadSemaphore and attrs perldoc pages.
  • Every program starts with a default thread the
    main thread.

gt perldoc ThreadQueue
4
new()
my thread Thread-gtnew(\calculate_pi,
precision gt 190)
pass the functions arguments
pass a function reference
NOTE This is an example of what are called
named parameters. Suppose we have a function
foo() with three parameters A, B and C. If we
supply default values to all three parameters
and call foo(Bgt4) then the default values are
used for parameters A and C and the parameter B
is passed a 4.
sub foo my params A gt 1, Bgt 2, Cgt
3 my args _at__ my (key, A,B,C)
foreach key (keys args)
paramskey argskey A
paramsA) B paramsB C
paramsC)
5
Detached Threads
  • Threads can be detached from their calling
    environment,
  • in which case the return value to
    calculate_pi() is lost to the calling
    environment.
  • Alternatively, the calling environment can wait
    for calculate_pi() to complete and recover its
    return value.
  • In fact, while only parents can wait() for a
    child, any thread can wait for another thread
    by calling join().
  • join() blocks until the executing thread
    terminates.
  • Threads terminate by having their subroutines
    return.
  • Thread subroutines should not call exit().

thread-gtdetach()
my pi thread-gtjoin()
6
Signal handlers
  • Only the main thread should install signal
    handlers. You have no guarantee what thread will
    receive a handled signal.
  • Threads can call die() and it wont kill the
    program immediately. It will kill the program
    once the corresponding call to join() returns.

my thread1 Thread-gtnew(\foo) my thread2
Thread-gtnew(\bar) thread1-gtjoin() thread2-gtj
oin()
sub bar die bar is dead
the program only terminates abnormally after both
threads complete.
7
But I dont want to die!!
my x eval thread2-gtjoin() warn And I
did not die!
the eval block catches the die() and only it
dies.
8
A Simple Example
!/usr/bin/perl hello.pl use Thread my thread1
Thread-gtnew(\hello, I am thread 1,3) my
thread2 Thread-gtnew(\hello, I am thread
2,6) _-gtjoin foreach (thread1,thread2) sub
hello my (msg,loop) _at__ for
(1..loop) print msg,\n
sleep 1
gt perl hello.pl I am thread 1 I am thread 2 I am
thread 1 I am thread 2 I am thread 1 I am thread
2 I am thread 2 I am thread 2 I am thread 2
9
Locking
my bytes_sent 0 my socket
IOSocket-gtnew(. . .) sub send_data my
data shift my bytes socket-gtsyswrite(da
ta) bytes_sent bytes
  • Suppose we have multiple connections, all writing
    at more or les the same time.
  • Thread 1 fetches a copy of bytes_sent and
    prepares to increment it
  • Context switch happens and thread 2 takes
    control. It fetches bytes_sent and increments
    it.
  • Context switch happens and thread 1 takes
    control. Thread 1 still holds the old value of
    bytes_sent which it updates and saves to the
    global location. Thread 2s changes are lost.

10
Locking (2)
  • This wont happan all the time but from time to
    time which is even worse.
  • The fix lock()

my bytes_sent 0 my socket
IOSocket-gtnew(. . .) sub send_data my
data shift my bytes socket-gtsyswrite(da
ta) lock(bytes_sent) bytes_sent
bytes
prevents others from attempting to get a lock on
bytes_sent but not from reading it. lock stays
in place until the end of the routine.
called an advisory lock
any other thread that tries to lock(bytes_sent)
is suspended until the lock is achieved.
11
Locking (3)
  • If you are modifying multiple variables dont try
    to lock them all.
  • Create a special variable just for locking.

my ok_to_update sub send_data my data
shift my bytes socket-gtsyswrite(data)
lock(ok_to_update) bytes_sent bytes
bytes_left - bytes
12
Locking (4)
  • You can also lock an entire subroutine.
  • When a subroutine is locked only one thread can
    execute it at a time.
  • Safe only for small routines otherwise we get
    threads in serial and not in parallel.

lock(\foo)
as is, up to 4 cars can be in the intersection at
a time but with lock(\use_intersection) o
nly one car at a time can.
13
Locking (5)
  • No need to lock unshared (local) variables.
  • Lock object references only if the object is
    shared by multiple threads.
  • Object methods that modify a shared object should
    lock the object

sub acknowledge not thread safe my self
shift print selfgtsocket 200 OK\n
self-gtacknowledged
sub acknowledge thread safe my self
shift lock(self) print selfgtsocket
200 OK\n self-gtacknowledged
what is being locked the object or the
reference? lock() follows references one level
only so lock(self) lock(self)
14
Locking (6)
sub acknowledge locked method my self
shift print selfgtsocket 200 OK\n
self-gtacknowledged
locks the object
sub acknowledge locked my self shift
print selfgtsocket 200 OK\n
self-gtacknowledged
locks the subroutine
Difference different connections (self)
can simultaneously use acknowledge() at the same
time in case 1 but not in case 2
15
Thread Functions
thread Thread-gtnew(\subroutine ,
_at_arguments) return_value thread-gtjoin() th
read-gtdetach()
  • new() creates and starts a new thread. join()
    blocks until the thread terminates. Once you
    detach() you can not join() later. The main
    thread is free.
  • list() returns a list of thread objects. The list
    includes running and dead but not joined threads
  • lock(_at_array) is not the same as lock(array2).

_at_threads Thread-gtlist() thread
Thread-gtself() tid thread-gttid() lock(varia
ble)
16
Thread Functions
use Thread qw(async yield coond_wait cond_signal
cond_broadcast) thread asyncBLOCK yield()
cond_wait(variable) cond_signal(variable) con
d_broadcast(variable)
  • All these need to be explicitly imported.
  • async is an alternative way to create a new
    thread.
  • yield() is the current thread hint that a
    context switch would be a good idea NOW.
  • unlocks a locked variable and waits until another
    thread signals the same variable with
    cond_signal() or cond_broadcast().

17
Thread Functions (2)
  • cond_signal(variable) signals variable,
    restarting any threads that are cond_waiting() on
    the same variable.
  • If multiple threads are waiting on variable, one
    and only one is woken up.
  • cond_broadcast(variable) signals variable,
    restarting all threads that are cond_waiting() on
    the same variable.
  • Each awakened thread acquires a lock on variable
    in turn.
  • In both cond_signal(variable) and
    cond_broadcast(variable) there is no way to
    determine which thread will be woken up.

18
Threads and Signals
  • The book tells us so little it is best to keep
    clear of it.

19
A Multithreaded Eliza
!/usr/bin/perl file eliza_thread.pl Figure
11.1 Multithreaded psychiatrist server use
strict use IOSocket use Thread use
ChatbotElizaServer use constant PORT gt
12000 my listen_socket IOSocketINET-gtnew(
LocalPort gt PORT,
Listen gt 20,
Proto gt 'tcp',
Reuse gt
1) die _at_ unless listen_socket warn
"Listening for connections...\n"
20
A Multithreaded Eliza (2)
while (my connection listen_socket-gtaccept)
Thread-gtnew(\interact,connection) sub
interact my handle shift
Thread-gtself-gtdetach ChatbotElizaServer-gtne
w-gtcommand_interface(handle,handle)
handle-gtclose()
listening server can ignore the service thread
new object
new object invokes method
21
A Multithreaded Eliza (3)
!/usr/bin/perl file eliza_thread.pl Figure
11.1 Multithreaded psychiatrist server use
strict use IOSocket use Thread use
ChatbotElizaServer use constant PORT gt
12000 my listen_socket IOSocketINET-gtnew(
LocalPort gt PORT,
Listen gt 20,
Proto gt 'tcp',
Reuse gt
1) die _at_ unless listen_socket warn
"Listening for connections...\n"
22
A Multithreaded Eliza (4)
package ChatbotElizaServer use
ChatbotEliza file Chatbot/Eliza/Server.pm
Figure 11.2 The ChatbotElizaServer
class _at_ISA 'ChatbotEliza' sub
command_interface my self shift my in
shift \STDIN my out shift
\STDOUT my (user_input, previous_user_input,
reply) self-gtbotprompt(self-gtname .
"\t") Set Eliza's prompt
self-gtuserprompt("you\t") Set
user's prompt Print an initial greeting
print out self-gtbotprompt,
self-gtinitial-gt int rand scalar _at_
self-gtinitial , "\n"
tells perl to look in CharbotEliza if it cant
find a method, botprompt() for example, in this
module.
size
index
23
A Multithreaded Eliza (5)
while (1) print out self-gtuserprompt
previous_user_input user_input
chomp( user_input ltingt ) last unless
user_input User wants to quit if
(self-gt_testquit(user_input) )
reply self-gtfinal-gt int rand scalar _at_
self-gtfinal print out
self-gtbotprompt,reply,"\n" last
Invoke the transform method to
generate a reply. reply
self-gttransform( user_input ) Print
the actual reply print out
self-gtbotprompt,reply,"\n" 1
24
A Multithreaded Client
!/usr/bin/perl file gab4.pl Figure 11.3
Threaded concurrent client usage gab4.pl
host port use strict use IOSocket use
Thread use constant BUFSIZE gt 1024 SIGTERM
sub exit 0 my host shift or die
"Usage gab4.pl host port" my port shift
'echo' my socket IOSocketINET-gtnew("host
port") or die _at_ thread reads from socket,
writes to STDOUT my read_thread
Thread-gtnew(\host_to_user,socket)
25
A Multithreaded Client
main thread reads from STDIN, writes to
socket user_to_host(socket) socket-gtshutdown(1)
read_thread-gtjoin sub user_to_host my
s shift my data syswrite(s,data)
while sysread(STDIN,data,BUFSIZE) sub
host_to_user my s shift my data
syswrite(STDOUT,data) while sysread(s,data,BUFS
IZE) return 0
1 shutdown() starts with EOF from STDIN
propagates EOF to server
3 when thread terminates join() returns and the
main thread exits.
2 server gets EOF and returns and in doing so
closes its end of the connection
26
(No Transcript)
Write a Comment
User Comments (0)
About PowerShow.com