在Java中多线程的同步

作者: Arvin Chen 分类: Java 来源: Break易站(www.breakyizhan.com)

多线程程序可能经常遇到多线程试图访问相同资源并最终产生错误和无法预料的结果的情况。

因此需要通过某种同步方法确保只有一个线程可以在给定的时间点访问资源。

Java提供了一种使用synchronized块创建线程和同步其任务的方法。Java中的同步块使用synchronized关键字标记。Java中的同步块在某个对象上同步。在同一对象上同步的所有同步块一次只能在其中执行一个线程。尝试进入同步块的所有其他线程将被阻塞,直到同步块内的线程退出块。

以下是同步块的一般形式:

// Only one thread can execute at a time. 
// sync_object is a reference to an object
// whose lock associates with the monitor. 
// The code is said to be synchronized on
// the monitor object
synchronized(sync_object)
{
   // Access shared variables and other
   // shared resources
}
在Java中使用称为监视器的概念实现。在给定时间只有一个线程可以拥有监视器。当线程获得锁定时,据说它已进入监视器。尝试进入锁定监视器的所有其他线程将被挂起,直到第一个线程退出监视器。

以下是使用synchronized进行多线程处理的示例。

// A Java program to demonstrate working of
// synchronized.
import java.io.*;
import java.util.*;

// A Class used to send a message
class Sender
{
    public void send(String msg)
    {
        System.out.println("Sending\t"  + msg );
        try
        {
            Thread.sleep(1000);
        }
        catch (Exception e)
        {
            System.out.println("Thread  interrupted.");
        }
        System.out.println("\n" + msg + "Sent");
    }
}

// Class for send a message using Threads
class ThreadedSend extends Thread
{
    private String msg;
    private Thread t;
    Sender  sender;

    // Recieves a message object and a string
    // message to be sent
    ThreadedSend(String m,  Sender obj)
    {
        msg = m;
        sender = obj;
    }

    public void run()
    {
        // Only one thread can send a message
        // at a time.
        synchronized(sender)
        {
            // synchronizing the snd object
            sender.send(msg);
        }
    }
}

// Driver class
class SyncDemo
{
    public static void main(String args[])
    {
        Sender snd = new Sender();
        ThreadedSend S1 =
            new ThreadedSend( " Hi " , snd );
        ThreadedSend S2 =
            new ThreadedSend( " Bye " , snd );

        // Start two threads of ThreadedSend type
        S1.start();
        S2.start();

        // wait for threads to end
        try
        {
            S1.join();
            S2.join();
        }
        catch(Exception e)
        {
            System.out.println("Interrupted");
        }
    }
}

输出:

Sending	 Hi 

 Hi Sent
Sending	 Bye 

 Bye Sent

每次运行程序时输出都是相同的。

在上面的示例中,我们选择在ThreadedSend类的run()方法内同步Sender对象。或者,我们可以将整个send()块定义为synchronized,它将产生相同的结果。然后我们不必在ThreadedSend类中的run()方法内同步Message对象。

// An alternate implementation to demonstrate
// that we can use synchronized with method also.
class Sender
{
    public synchronized void send(String msg)
    {
        System.out.println("Sending\t" + msg );
        try
        {
            Thread.sleep(1000);
        }
        catch (Exception e)
        {
            System.out.println("Thread interrupted.");
        }
        System.out.println("\n" + msg + "Sent");
    }
}

我们并不总是需要同步整个方法。有时最好只同步方法的一部分。方法中的Java同步块使这成为可能。

// One more alternate implementation to demonstrate
// that synchronized can be used with only a part of
// method
class Sender
{
    public void send(String msg)
    {
        synchronized(this)
        {
            System.out.println("Sending\t" + msg );
            try
            {
                Thread.sleep(1000);
            }
            catch (Exception e)
            {
                System.out.println("Thread interrupted.");
            }
            System.out.println("\n" + msg + "Sent");
        }
    }
}
  •   本文标题:在Java中多线程的同步 - Break易站
    转载请保留页面地址:https://www.breakyizhan.com/java/4962.html

    发表笔记

    电子邮件地址不会被公开。 必填项已用*标注

    更多阅读