From $ROOTSYS/tutorials/thread/threadsh1.C

//+ Example of a simple script creating 3 threads.
// This script can only be executed via ACliC .x threadsh1.C++.

#include "TCanvas.h"
#include "TFrame.h"
#include "TH1F.h"
#include "TRandom.h"
#include "TThread.h"


TCanvas *c[4];
TH1F    *hpx[4];
TThread *t[5];
Bool_t finished;

void *handle(void *ptr)
{
   long nr = (long) ptr;
   Long64_t nfills = 25000000;
   int upd = 50000;

   char name[32];
   sprintf(name,"hpx%ld",nr);
   TThread::Lock();
   hpx[nr] = new TH1F(name,"This is the px distribution",100,-4,4);
   hpx[nr]->SetFillColor(48);
   TThread::UnLock();
   Float_t px, py, pz;
   gRandom->SetSeed();
   for (Int_t i = 0; i < nfills; i++) {
      gRandom->Rannor(px,py);
      pz = px*px + py*py;
      hpx[nr]->Fill(px);
      if (i && (i%upd) == 0) {
         if (i == upd) {
            TThread::Lock();
            c[nr]->cd();
            hpx[nr]->Draw();
            TThread::UnLock();
         }
         if (c[nr]) c[nr]->Modified();
         gSystem->Sleep(10);
      }
   }
   return 0;
}

void *joiner(void *)
{
   t[0]->Join();
   t[1]->Join();
   t[2]->Join();
   t[3]->Join();

   finished = kTRUE;

   return 0;
}

void closed(Int_t id)
{
   // kill the thread matching the canvas being closed 
   t[id]->Kill();
   // and set the canvas pointer to 0
   c[id] = 0;
}

void threadsh1()
{
#ifdef __CINT__
   printf("This script can only be executed via ACliC: .x threadsh1.C++\n");
   return;
#endif

   finished = kFALSE;
   //gDebug = 1;

   c[0] = new TCanvas("c0","Dynamic Filling Example",100,20,400,300);
   c[0]->SetFillColor(42);
   c[0]->GetFrame()->SetFillColor(21);
   c[0]->GetFrame()->SetBorderSize(6);
   c[0]->GetFrame()->SetBorderMode(-1);
   c[1] = new TCanvas("c1","Dynamic Filling Example",510,20,400,300);
   c[1]->SetFillColor(42);
   c[1]->GetFrame()->SetFillColor(21);
   c[1]->GetFrame()->SetBorderSize(6);
   c[1]->GetFrame()->SetBorderMode(-1);
   c[2] = new TCanvas("c2","Dynamic Filling Example",100,350,400,300);
   c[2]->SetFillColor(42);
   c[2]->GetFrame()->SetFillColor(21);
   c[2]->GetFrame()->SetBorderSize(6);
   c[2]->GetFrame()->SetBorderMode(-1);
   c[3] = new TCanvas("c3","Dynamic Filling Example",510,350,400,300);
   c[3]->SetFillColor(42);
   c[3]->GetFrame()->SetFillColor(21);
   c[3]->GetFrame()->SetBorderSize(6);
   c[3]->GetFrame()->SetBorderMode(-1);

   // connect to the Closed() signal to kill the thread when a canvas is closed
   c[0]->Connect("Closed()", 0, 0, "closed(Int_t=0)");
   c[1]->Connect("Closed()", 0, 0, "closed(Int_t=1)");
   c[2]->Connect("Closed()", 0, 0, "closed(Int_t=2)");
   c[3]->Connect("Closed()", 0, 0, "closed(Int_t=3)");

   printf("Starting Thread 0\n");
   t[0] = new TThread("t0", handle, (void*) 0);
   t[0]->Run();
   printf("Starting Thread 1\n");
   t[1] = new TThread("t1", handle, (void*) 1);
   t[1]->Run();
   printf("Starting Thread 2\n");
   t[2] = new TThread("t2", handle, (void*) 2);
   t[2]->Run();
   printf("Starting Thread 3\n");
   t[3] = new TThread("t3", handle, (void*) 3);
   t[3]->Run();
   printf("Starting Thread 4\n");
   t[4] = new TThread("t4", joiner, (void*) 3);
   t[4]->Run();

   TThread::Ps();

   while (!finished) {
      for (int i = 0; i < 4; i++) {
         if (c[i] && c[i]->IsModified()) {
            //printf("Update canvas %d\n", i);
            c[i]->Update();
         }
      }
      gSystem->Sleep(100);
      gSystem->ProcessEvents();
   }

   t[4]->Join();
   TThread::Ps();

   delete t[0];
   delete t[1];
   delete t[2];
   delete t[3];
   delete t[4];
}
 threadsh1.C:1
 threadsh1.C:2
 threadsh1.C:3
 threadsh1.C:4
 threadsh1.C:5
 threadsh1.C:6
 threadsh1.C:7
 threadsh1.C:8
 threadsh1.C:9
 threadsh1.C:10
 threadsh1.C:11
 threadsh1.C:12
 threadsh1.C:13
 threadsh1.C:14
 threadsh1.C:15
 threadsh1.C:16
 threadsh1.C:17
 threadsh1.C:18
 threadsh1.C:19
 threadsh1.C:20
 threadsh1.C:21
 threadsh1.C:22
 threadsh1.C:23
 threadsh1.C:24
 threadsh1.C:25
 threadsh1.C:26
 threadsh1.C:27
 threadsh1.C:28
 threadsh1.C:29
 threadsh1.C:30
 threadsh1.C:31
 threadsh1.C:32
 threadsh1.C:33
 threadsh1.C:34
 threadsh1.C:35
 threadsh1.C:36
 threadsh1.C:37
 threadsh1.C:38
 threadsh1.C:39
 threadsh1.C:40
 threadsh1.C:41
 threadsh1.C:42
 threadsh1.C:43
 threadsh1.C:44
 threadsh1.C:45
 threadsh1.C:46
 threadsh1.C:47
 threadsh1.C:48
 threadsh1.C:49
 threadsh1.C:50
 threadsh1.C:51
 threadsh1.C:52
 threadsh1.C:53
 threadsh1.C:54
 threadsh1.C:55
 threadsh1.C:56
 threadsh1.C:57
 threadsh1.C:58
 threadsh1.C:59
 threadsh1.C:60
 threadsh1.C:61
 threadsh1.C:62
 threadsh1.C:63
 threadsh1.C:64
 threadsh1.C:65
 threadsh1.C:66
 threadsh1.C:67
 threadsh1.C:68
 threadsh1.C:69
 threadsh1.C:70
 threadsh1.C:71
 threadsh1.C:72
 threadsh1.C:73
 threadsh1.C:74
 threadsh1.C:75
 threadsh1.C:76
 threadsh1.C:77
 threadsh1.C:78
 threadsh1.C:79
 threadsh1.C:80
 threadsh1.C:81
 threadsh1.C:82
 threadsh1.C:83
 threadsh1.C:84
 threadsh1.C:85
 threadsh1.C:86
 threadsh1.C:87
 threadsh1.C:88
 threadsh1.C:89
 threadsh1.C:90
 threadsh1.C:91
 threadsh1.C:92
 threadsh1.C:93
 threadsh1.C:94
 threadsh1.C:95
 threadsh1.C:96
 threadsh1.C:97
 threadsh1.C:98
 threadsh1.C:99
 threadsh1.C:100
 threadsh1.C:101
 threadsh1.C:102
 threadsh1.C:103
 threadsh1.C:104
 threadsh1.C:105
 threadsh1.C:106
 threadsh1.C:107
 threadsh1.C:108
 threadsh1.C:109
 threadsh1.C:110
 threadsh1.C:111
 threadsh1.C:112
 threadsh1.C:113
 threadsh1.C:114
 threadsh1.C:115
 threadsh1.C:116
 threadsh1.C:117
 threadsh1.C:118
 threadsh1.C:119
 threadsh1.C:120
 threadsh1.C:121
 threadsh1.C:122
 threadsh1.C:123
 threadsh1.C:124
 threadsh1.C:125
 threadsh1.C:126
 threadsh1.C:127
 threadsh1.C:128
 threadsh1.C:129
 threadsh1.C:130
 threadsh1.C:131
 threadsh1.C:132
 threadsh1.C:133
 threadsh1.C:134
 threadsh1.C:135
 threadsh1.C:136
 threadsh1.C:137
 threadsh1.C:138
 threadsh1.C:139
 threadsh1.C:140
 threadsh1.C:141
 threadsh1.C:142
 threadsh1.C:143