Java中用于无锁算法的 AtomicInteger
无锁算法是一种机制,在这种机制中,可以在不使用互斥锁等同步原语的情况下,线程安全地访问共享数据。多线程应用程序具有可以在应用程序中使用的不同线程之间传递的共享资源。
- 这构成了线程之间竞争条件和数据竞争的威胁。为了处理这种情况,使用了各种技术。最常见的方法之一是使用同步和锁(也称为监视器)来确保线程安全。但是,如果使用过多的同步,随着应用程序变得越来越复杂,应用程序性能将受到巨大影响。
- 我们需要编写线程安全的应用程序,但同时它们应该为我们提供高性能和并发执行的好处。所以,为了尽量减少同步的使用,降低锁的复杂性, Java在Java包中有一整套类,提供了许多无锁和原子的高级操作。
- 可以在应用程序中执行大量操作,而无需同步大部分代码。我们需要了解在某种情况下什么最适用,并为工作使用正确的工具。
- 我们将看到一个示例,首先我们展示如何在多线程应用程序中使用同步锁来实现并发,然后我们将看到一个解决方案,该解决方案提供了针对同一问题的无锁解决方案。
以下示例显示了如何将同步和锁定机制用作并发解决方案。
Java
// Java Program to demonstrate the
// Synchronization of threads
// using Locks
import java.io.*;
class GFG {
public static void main(String[] args)
throws InterruptedException
{
// Creating Obj for CountTrees Class
CountTrees countTrees = new CountTrees();
// Creating Obj for IncreaseTrees Class
IncreaseTrees increaseTreesThread = new IncreaseTrees(countTrees);
// Creating Obj for IncreaseConcrete Class
IncreaseConcrete increaseConcreteThread
= new IncreaseConcrete(countTrees);
// Starting both Thread increaseTreesThread
// And increaseConcreteThread by using start method.
increaseTreesThread.start();
increaseConcreteThread.start();
// Join method Enable threads wait to complete
increaseTreesThread.join();
increaseConcreteThread.join();
// To print the no. of trees by getting current
// value by using countTrees Obj.
System.out.println("Number of trees in your area ::"
+ countTrees.getNumOfTrees());
}
}
// Implementation of IncreaseTrees using Thread
class IncreaseTrees extends Thread {
private CountTrees countTrees;
IncreaseTrees(CountTrees countTrees)
{
this.countTrees = countTrees;
}
@Override
public void run()
{
System.out.println("Planting trees in progress...");
countTrees.plantTrees();
}
}
// Implementation of IncreaseConcrete using Thread
class IncreaseConcrete extends Thread {
private CountTrees countTrees;
IncreaseConcrete(CountTrees countTrees)
{
this.countTrees = countTrees;
}
@Override
public void run()
{
System.out.println("Concretization in progress...");
countTrees.concretizing();
}
}
// Synchronizing the shared resources
class CountTrees {
private int trees = 10000;
public synchronized void plantTrees()
{
for (int i = 0; i < 10000; i++)
trees++;
}
public synchronized void concretizing()
{
for (int i = 0; i < 10000; i++)
trees--;
}
public synchronized int getNumOfTrees()
{
return this.trees;
}
}
Java
// Java program to demonstrate to achieve concurrency
// with the help of AtomicInteger class which is used
// in application like atomically incremented the counter
// Lock Free program for achieving concurrency
import java.io.*;
// Java provides wrapper class to achieve atomic
// operations without the use of synchronization
// like java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicInteger;
class GFG {
public static void main(String[] args)
throws InterruptedException
{
// Creating Obj for CountTrees Class
CountTrees countTrees = new CountTrees();
// Creating Obj for IncreaseTrees Class
IncreaseTrees increaseTreesThread
= new IncreaseTrees(countTrees);
// Creating Obj for IncreaseConcrete Class
IncreaseConcrete increaseConcreteThread
= new IncreaseConcrete(countTrees);
// Starting both Thread increaseTreesThread
// and increaseConcreteThread by using
// start method.
increaseTreesThread.start();
increaseConcreteThread.start();
// join method Enable threads wait to complete
increaseTreesThread.join();
increaseConcreteThread.join();
// To print the no. of trees by getting current
// value by using countTrees Obj.
System.out.println("Number of trees in your area ::"
+ countTrees.getNumOfTrees());
}
}
// Implementation of IncreaseTrees class
class IncreaseTrees extends Thread {
private CountTrees countTrees;
IncreaseTrees(CountTrees countTrees)
{
this.countTrees = countTrees;
}
@Override public void run()
{
System.out.println("Planting trees in process...");
countTrees.plantTrees();
}
}
class IncreaseConcrete extends Thread {
private CountTrees countTrees;
IncreaseConcrete(CountTrees countTrees)
{
this.countTrees = countTrees;
}
@Override public void run()
{
System.out.println("Concretization in progress...");
countTrees.concretizing();
}
}
// Implementation of CountTrees Class
class CountTrees {
// In java AtomicInteger Class provides operations on
// underlying int value that can be read and
// written atomically.
private AtomicInteger trees = new AtomicInteger(10000);
// Implementation of plantTrees method
public void plantTrees()
{
// AtomicInteger class obj trees
// atomically incremented the value.
for (int i = 0; i < 10000; i++)
trees.incrementAndGet();
}
// Implementation of concretizing method
public void concretizing()
{
// AtomicInteger class obj trees
// decremented the value.
for (int i = 0; i < 10000; i++)
trees.decrementAndGet();
}
public int getNumOfTrees()
{
// AtomicInteger class obj
// trees Gets the current
// value.
return trees.get();
}
}
输出:
Planting trees in progress...
Concretization in progress...
Number of trees in your area:: 10000
现在要将上面的示例转换为一个简单的无锁示例,我们使用Java的AtomicInteger类,它是 Concurrent 包Java.util.concurrent.atomic.AtomicInteger的一部分。这是一个非常有用的类,可以很容易地在并发应用程序中使用,如下所示:
Java
// Java program to demonstrate to achieve concurrency
// with the help of AtomicInteger class which is used
// in application like atomically incremented the counter
// Lock Free program for achieving concurrency
import java.io.*;
// Java provides wrapper class to achieve atomic
// operations without the use of synchronization
// like java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicInteger;
class GFG {
public static void main(String[] args)
throws InterruptedException
{
// Creating Obj for CountTrees Class
CountTrees countTrees = new CountTrees();
// Creating Obj for IncreaseTrees Class
IncreaseTrees increaseTreesThread
= new IncreaseTrees(countTrees);
// Creating Obj for IncreaseConcrete Class
IncreaseConcrete increaseConcreteThread
= new IncreaseConcrete(countTrees);
// Starting both Thread increaseTreesThread
// and increaseConcreteThread by using
// start method.
increaseTreesThread.start();
increaseConcreteThread.start();
// join method Enable threads wait to complete
increaseTreesThread.join();
increaseConcreteThread.join();
// To print the no. of trees by getting current
// value by using countTrees Obj.
System.out.println("Number of trees in your area ::"
+ countTrees.getNumOfTrees());
}
}
// Implementation of IncreaseTrees class
class IncreaseTrees extends Thread {
private CountTrees countTrees;
IncreaseTrees(CountTrees countTrees)
{
this.countTrees = countTrees;
}
@Override public void run()
{
System.out.println("Planting trees in process...");
countTrees.plantTrees();
}
}
class IncreaseConcrete extends Thread {
private CountTrees countTrees;
IncreaseConcrete(CountTrees countTrees)
{
this.countTrees = countTrees;
}
@Override public void run()
{
System.out.println("Concretization in progress...");
countTrees.concretizing();
}
}
// Implementation of CountTrees Class
class CountTrees {
// In java AtomicInteger Class provides operations on
// underlying int value that can be read and
// written atomically.
private AtomicInteger trees = new AtomicInteger(10000);
// Implementation of plantTrees method
public void plantTrees()
{
// AtomicInteger class obj trees
// atomically incremented the value.
for (int i = 0; i < 10000; i++)
trees.incrementAndGet();
}
// Implementation of concretizing method
public void concretizing()
{
// AtomicInteger class obj trees
// decremented the value.
for (int i = 0; i < 10000; i++)
trees.decrementAndGet();
}
public int getNumOfTrees()
{
// AtomicInteger class obj
// trees Gets the current
// value.
return trees.get();
}
}
输出:
Concretization in progress...
Planting trees in process...
Number of trees in your area::10000
总结和关键要点:
- AtomicInteger类是一个很好的工具,可用于简单的应用程序,如并发计数和构建简单可读的代码,而无需使用锁的复杂性。
- 只有在需要原子操作时才应使用AtomicInteger 。此外,竞争条件仍然可以存在于两个单独的原子操作之间。
- AtomicInteger类是同等的,有时比使用锁作为保护的常规整数更有效。
- 如果应用程序仅使用单个线程,则首选常规整数。
参考资料: Java中的 AtomicInteger 类