কম্পিউটার টিউটোরিয়াল

সি প্রোগ্রামিং-এ মাল্টিথ্রেডিং


মাল্টিথ্রেডিং কী?

মাল্টিথ্রেডিং হলো মাল্টিটাস্কিং-এর একটি বিশেষ রূপ। মাল্টিটাস্কিং হলো সেই বৈশিষ্ট্য যা আপনার কম্পিউটারকে দুটি বা তার অধিক প্রোগ্রাম একসাথে চালাতে দেয়। সাধারণত মাল্টিটাস্কিং দুটি প্রকারের:

  • প্রসেস-ভিত্তিক মাল্টিটাস্কিং: প্রোগ্রামগুলোর সমকালীন এক্সিকিউশন পরিচালনা করে।
  • থ্রেড-ভিত্তিক মাল্টিটাস্কিং: একই প্রোগ্রামের বিভিন্ন অংশের সমকালীন এক্সিকিউশন নিয়ে কাজ করে।

একটি মাল্টিথ্রেডেড প্রোগ্রামে দুটি বা তার অধিক অংশ থাকে যা একসাথে চালানো যায়। এমন প্রোগ্রামের প্রতিটি অংশকে থ্রেড বলা হয়, এবং প্রতিটি থ্রেড এক্সিকিউশনের আলাদা পথ নির্ধারণ করে।

সি-তে মাল্টিথ্রেডিং সাপোর্ট

সি-তে মাল্টিথ্রেডেড অ্যাপ্লিকেশনের জন্য কোনো বিল্ট-ইন সাপোর্ট নেই। এটি সম্পূর্ণরূপে অপারেটিং সিস্টেমের ওপর নির্ভর করে।

এই টিউটোরিয়ালে আমরা লিনাক্স ওএস ধরে কাজ করব এবং POSIX (Pthreads) ব্যবহার করে মাল্টি-থ্রেডেড সি প্রোগ্রাম লিখব। POSIX থ্রেডস বা Pthreads অনেক ইউনিক্স-লাইক সিস্টেমে (FreeBSD, NetBSD, GNU/Linux, Mac OS X, Solaris) উপলব্ধ একটি API প্রদান করে।

POSIX থ্রেড তৈরি করা

নিচের রুটিন ব্যবহার করে একটি POSIX থ্রেড তৈরি করা হয়:

#include <pthread.h>
pthread_create(thread, attr, start_routine, arg)

এখানে, pthread_create একটি নতুন থ্রেড তৈরি করে এবং এক্সিকিউটেবল করে। এই রুটিনটি আপনার কোডের যেকোনো জায়গা থেকে যেকোনো সংখ্যক বার কল করা যেতে পারে। প্যারামিটারগুলোর বিবরণ নিচে দেওয়া হলো:

প্যারামিটারবিবরণ
threadসাবরুটিন দ্বারা রিটার্ন করা নতুন থ্রেডের জন্য একটি অস্পষ্ট, ইউনিক আইডেন্টিফায়ার।
attrএকটি অস্পষ্ট অ্যাট্রিবিউট অবজেক্ট যা থ্রেড অ্যাট্রিবিউট সেট করতে ব্যবহৃত হতে পারে। ডিফল্ট মানের জন্য NULL নির্দিষ্ট করা যেতে পারে।
start_routineসি রুটিন যা থ্রেড তৈরি হওয়ার পর এক্সিকিউট করবে।
argstart_routine-এ পাস করার জন্য একটি একক আর্গুমেন্ট। এটি রেফারেন্স হিসেবে পাস করা হয় (void টাইপে কাস্ট করে)। কোনো আর্গুমেন্ট না থাকলে NULL ব্যবহার করা যেতে পারে।

একটি প্রসেস দ্বারা তৈরি করা যাওয়া সর্বোচ্চ থ্রেডের সংখ্যা ইমপ্লিমেন্টেশনের ওপর নির্ভরশীল। একবার তৈরি হলে, থ্রেডগুলি পিয়ার হয় এবং অন্যান্য থ্রেড তৈরি করতে পারে। থ্রেডগুলোর মধ্যে কোনো আপনীত হায়ারার্কি বা নির্ভরতা নেই।

থ্রেড টার্মিনেট করা

একটি POSIX থ্রেড টার্মিনেট করতে নিচের রুটিন ব্যবহার করা হয়:

#include <pthread.h>
pthread_exit(status)

এখানে pthread_exit একটি থ্রেড থেকে স্পষ্টভাবে বের হওয়ার জন্য ব্যবহৃত হয়। সাধারণত, একটি থ্রেড তার কাজ শেষ করার পর এবং আর অস্তিত্বে থাকার প্রয়োজন না থাকলে pthread_exit() কল করা হয়।

যদি main() তৈরি করা থ্রেডها শেষ হওয়ার আগে pthread_exit() দিয়ে বের হয়, তবে অন্যান্য থ্রেড এক্সিকিউট होते থাকবে। অন্যথায়, main() শেষ হলে সেগুলো স্বয়ংক্রিয়ভাবে টার্মিনেট হবে।

উদাহরণ কোড

#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;

#define NUM_THREADS 5

void *PrintHello(void *threadid) {
    long tid;
    tid = (long)threadid;
    printf("Hello World! Thread ID, %d\n", tid);
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    int rc;
    int i;
    for(i = 0; i < NUM_THREADS; i++) {
        cout << "main() : creating thread, " << i << endl;
        rc = pthread_create(&threads[i], NULL, PrintHello, (void *)i);
        if (rc) {
            printf("Error: unable to create thread, %d\n", rc);
            exit(-1);
        }
    }
    pthread_exit(NULL);
}

আউটপুট

$gcc test.cpp -lpthread
$./a.out
main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Hello World! Thread ID, 0
Hello World! Thread ID, 1
Hello World! Thread ID, 2
Hello World! Thread ID, 3
Hello World! Thread ID, 4
  1. জাভা মাল্টিথ্রেডিং-এ থ্রেড প্রায়োরিটি (Thread Priority)

  2. জাভাতে থ্রেড বন্ধ করা

  3. জাভাতে থ্রেড পুল (Thread Pools)

  4. জাভাতে অ্যানোনিমাস ক্লাস ব্যবহার করে থ্রেড তৈরি করা