Javatpoint Logo
Javatpoint Logo

Counting Problem in Multithreading in Java

Java supports single-thread as well as multi-thread operations. A single-thread program has a single entry point (the main() method) and an exit point. A multi-thread program has an initial entry point (the main() method), followed by many entry and exit points that are run concurrently with the main() method. The term concurrency refers to doing multiple tasks at the same time.

Java has built-in support for concurrent programming by running multiple threads concurrently within a single program. A thread, also called a lightweight process, is a single sequential flow of programming operations, with a definite beginning and an end. During the lifetime of the thread, there is only a single point of execution. A thread by itself is not a program because it cannot run on its own. Instead, it runs within a program.

Multitasking (or Multi-processing)

Modern operating systems (such as Windows and UNIX) are multitasking system. A multitasking system can perform many tasks concurrently by sharing the computing resources, such as CPU(s), main memory, and I/O channels. In a single-CPU machine, only one task can be executed at one time - through time-slicing of the CPU. In a multi-CPU machine, a few tasks can be executed simultaneously, either distributed among or time-slicing the CPUs.

Multitasking is necessary in today's operating systems for better performance by making full use and optimize the usage of the computing resources. There are generally two kinds of multitasking operating systems:

  • Co-operative multitasking systems: Each task must voluntarily yield control to other tasks. This has the drawback that a run-away or uncooperative task may hang the entire system.
  • Pre-emptive multitasking systems: Tasks are given time-slices of the CPU(s) and will be forced to yield control to other tasks once their allocation is used up.

Multithreading (within a Process)

In UNIX, we fork a new process. In Windows, we start a program. A process or program has its own address space and control blocks. It is called heavyweight because it consumes a lot of system resources. Within a process or program, we can run multiple threads concurrently to improve the performance.

Threads, unlike heavyweight process, are lightweight and run inside a single process - they share the same address space, the resources allocated and the environment of that process. It is lightweight because it runs within the context of a heavyweight process and takes advantage of the resources allocated for that program and the program's environment. A thread must carve out its own resources within the running process. For example, a thread has its own stack, registers and program counter. The code running within the thread works only within that context, hence, a thread (of a sequential flow of operations) is also called an execution context.

Multithreading within a program improves the performance of the program by optimizing the usage of system resources. For example, while one thread is blocked (e.g., waiting for completion of an I/O operation), another thread can use the CPU time to perform computations, resulted in better performance and overall throughput.

Multithreading is also necessary to provide better interactivity with the users. For example, in a word processor, while one thread is printing or saving the file, another thread can be used to continue typing. In GUI applications, multithreading is essential in providing a responsive user interface.

For this article, I shall assume that we understand Swing programming, as Swing applications rely on multithreading (to perform their specific function, repaint and process the events) and best to illustrate multithreading.

A typical Java program runs in a single process, and is not interested in multiple processes. However, within the process, it often uses multiple threads to run multiple tasks concurrently. A standalone Java application starts with a single thread (called main thread) associated with the main() method. This main thread can then start new user threads.

Counter.java

Output:

Final Count: 6743

In this example, multiple threads increment the counter in a loop. However, since the increment method is not synchronized, there is a chance of race conditions, and the final count may not be as expected.

SynchronizedCounter.java

Output:

Final Count: 10000

Example of Counting Semaphore

A binary semaphore is known as a Counting semaphore with one permit because it only has two state permits available or unavailable permits. To execute mutual exclusion or critical section where only one thread is allowed to execute, a binary semaphore can be used. A thread waits on acquire() until Thread allows release within the critical section by calling release() on the semaphore. Below is java semaphore counting where binary semaphore is used to provide shared exclusive access to essential code parts

SemaphoreTest.java

Output:

Thread-0 inside mutual exclusive 
Thread-1 inside mutual exclusive 
Thread-0 outside of mutual exclusive 
Thread-1 outside of mutual exclusive






Youtube For Videos Join Our Youtube Channel: Join Now

Feedback


Help Others, Please Share

facebook twitter pinterest

Learn Latest Tutorials


Preparation


Trending Technologies


B.Tech / MCA