- 线程的同步

news/2024/7/5 9:34:47

1. 线程同步是对不同线程的协调。

2. 线程之间的四种关系(1)不相关的线程。(2)相关但无需同步的线程。(3)互斥线程。(4)相互通信式互斥线程。

3. 不相关的线程。用以执行不同功能的线程之间没有任何交互关系。

4. 相关但无需同步的线程。可用于分解处理任务。采用一组线程,使之分别作用于同一数据结构的不同数据部分,线程之间没有交互关系。eg1. 为每个套接字连接请求创建一个新的线程。eg2. 守护线程。

5. 守护线程。demon或daemon。守护线程以后台方式运行,用于为其他程序或线程提供服务。

// 设定为守护线程
myThread.setDemon(true);

Java程序不会停止守护线程。eg. 维护打印机队列的线程。

6. 启动多个相同的线程,为解决同一问题而分别处理不同的数据部分。

7. 测试一个给定的数值是否为素数。把给定的数值分成不同的数值段,从而确定线程的数量,由每个线程分别测算划定数值段内的每一个数值。

质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数。

class TestRange extends Thread{
    static long possPrime;
    long from, to;

    TestRange(int from, long possPrime){
        this.possPrime = possPrime;
        this.from = (from == 0) ? 2 : from;
        this.to = from + 99;
    }

    public void run(){
        for(long i = from; i <= to && i < possPrime; i++){
            if(possPrime % i == 0){
                break;
            }
            yield();
        }
    }
}

8. 在Java API中,Thread类中有三个方法已被停用:(1)挂起suspend(); (2)恢复resume(); (3)停止stop();

9. 线程的停止。应当采用编码方式的实现,即通过修改某一变量,通知目标线程停止运行。目标线程应该定期查看这个变量。

10. 如果想要停止因I/O问题而挂起或处于封锁状态的线程,可通过调用interrupt()方法,向线程发送一个异常信息。

11. 互斥线程。在一定的时间内,线程需要采用互斥方式运行。当线程需要操作同一数据结构中的同一数据部分时,这些线程必须相互等待以免同时修改同一数据,造成数据结果的不确定性。这些线程就是互斥线程。

12. join()方法。主线程将使用线程的join()方法等待每个线程的完成。

public class P
{
    // 气压表的当前读数
    static int pressureGauge = 0;
    // 气压安全范围上线
    static final int safetyLimit = 20;
    
    public static void main(String[] args)
    {
        Pressure[] p1 = new Pressure[10];
        for(int i = 0; i < 10; i++)
        {
            p1[i] = new Pressure();
            p1[i].start();
        }
        // 等待线程结束
        for(int i = 0; i < 10; i++)
        {
            try
            {
                p1[i].join();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        System.out.println("气压表当前读数是:" + pressureGauge + "\n气压安全范围上线:" + safetyLimit);
    }
    
    static class Pressure extends Thread
    {
        void raisePressure()
        {
            if(P.pressureGauge < P.safetyLimit - 15)
            {
                try
                {
                    sleep(100);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                P.pressureGauge += 15;
            }
        }
        public void run()
        {
            raisePressure();
        }
    }
}

 13. 当两个或多个线程同时更新同一个数值时,竞争条件(数据竞争)就会出现。在通常的数据竞争情况下,最困难的问题是无法调试。这是不可重复的问题,我们无法预知数据何时会出现不一致的情况。

14. 线程同步的解决方案。用以确保并发情况下数据的完整性。

(1)测试和设置指令。所有的通用CPU都具有这种指令。指令本身不提供封锁功能,但可以基于这种指令实现高级的同步控制机制。

(2)PV信号灯。信号灯一直是一种主要的同步原语。信号灯可以进行加减计数:P意味着减1操作,V意味着加1操作。利用测试和设置指令很容易实现信号灯控制原理。信号灯是一种底层的控制机制,程序员很难读取和调试,但可以使用信号灯实现高级的控制机制。

(3)读写锁(互斥锁)。提供一种简单的同步控制机制。在任何给定的时刻,只有一个线程能够执行互斥锁保护的代码块。利用信号灯,很容易实现互斥锁。

(4)监控器。是一种基于锁和变量的高级同步控制机制,其中的变量可用于跟踪某些相关的条件。利用读写锁,很容易实现监控器。监控器定义了若干方法,其中两个预定义的方法是wait()和notify()。

15. 在采用何种同步技术方面,并没有一个通用的标准。

16. 避免数据竞争。(1)无论两个线程何时访问同一个数据,必须采用互斥的方法进行处理。(2)在任意时刻允许两个线程同时读数据,但不允许有两个以上的线程对同一数据同时进行读写。(3)两个线程更不能同时写一个数据。

17. 线程互斥。互斥是一种保持同步的协议,可以确保当一个线程访问某一特定的数据时,其他线程不会再操作同一数据。在Java中,线程的互斥是建立在对象数据基础之上的。系统中的任何对象都可以用做线程的同步控制。我们可以显式地使用synchronized关键字,或隐式地提供一个用于同步的对象。运行时系统将负责控制并提供必要的代码,确保在一个给定的时刻最多只有一个线程能够锁住特定的对象。

18. synchronized(同步的)关键字。可用于(1)类方法(2)实例方法(3)代码块。在每一种情况下,都必须获取一个指定对象的互斥锁,然后才能执行代码块,直到代码块执行结束后才释放锁。

19. 程序员惟一需要做的是:指定需要互斥执行的代码区和对象。在指定互斥执行的代码区时要尽可能地小一些,因为互斥执行会影响系统的性能。

20. 使用synchronized关键字。同步代码块。如果可能的话,最好使用正被更新的对象作为同步锁。

在这个例子中,被更新的变量是整数类型,都不是对象类型,所以借用Object对象。只有获取对象o的互斥锁,才可以执行指定的代码区。

public class P
{
    // 气压表的当前读数
    static int pressureGauge = 0;
    // 气压安全范围上线
    static final int safetyLimit = 20;
    
    static Object o = new Object();
    
    public static void main(String[] args)
    {
        Pressure[] p1 = new Pressure[10];
        for(int i = 0; i < 10; i++)
        {
            p1[i] = new Pressure();
            p1[i].start();
        }
        // 等待线程结束
        for(int i = 0; i < 10; i++)
        {
            try
            {
                p1[i].join();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        System.out.println("气压表当前读数是:" + pressureGauge + "\n气压安全范围上线:" + safetyLimit);
    }
    
    static class Pressure extends Thread
    {
        void raisePressure()
        {
            if(P.pressureGauge < P.safetyLimit - 15)
            {
                try
                {
                    sleep(100);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                P.pressureGauge += 15;
            }
        }
        public void run()
        {
            synchronized (o)
            {
                raisePressure();
            }
        }
    }
}

21. 同步类方法。在这种情况下,提供互斥锁的对象是隐式的。

把一个static修饰的方法指定为同步的(synchronized),在任何给定的时间里,只有一个类对象可以执行static synchronized修饰的方法。

 

static class Pressure extends Thread
{
    static synchronized void raisePressure()
    {
        if(P.pressureGauge < P.safetyLimit - 15)
        {
            try
            {
                sleep(100);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            P.pressureGauge += 15;
        }
    }
    public void run()
    {
        raisePressure();
    }
}

 

22. 同步实例方法。在这种情况下,提供互斥锁的对象是隐式的,也就是方法调用对应的this对象。

为了把一个实例的方法定义为互斥的,可以把关键字synchronized加到实例方法的前面。

 

 


http://www.niftyadmin.cn/n/3855214.html

相关文章

java:多线程与Socket结合的简单示例

java:多线程与Socket结合的简单示例import java.io.*; import java.net.*; public class MyServer {public static void main(String[] args) throws IOException {ServerSocket server new ServerSocket(5678);Socket client server.accept();BufferedReader in new Buffer…

cocos2d-x开发之sqlite数据库加密研究(sqlite3.c代码浅析1)

SQLITE版本3.7.15.1中的sqlite3.c长达13万多行&#xff0c;要细致分析这个文件可不容易。但是&#xff0c;这个文件是由许多个.H和.C文件组合而成&#xff0c;正如此文件开始的注释中所述&#xff1a;/**********************************************************************…

Openstack(两控制节点+四计算节点)-4 模拟控制节点宕机

为什么80%的码农都做不了架构师&#xff1f;>>> 双控制节点通过heartbeatpacemaker监控相关服务&#xff0c;所以须在两台控制节点上先安装heartbeat软件&#xff0c;安装过程可参照&#xff1a; http://my.oschina.net/guol/blog/90128 pacemaker主要是对控制节点…

行业网站优化一般步骤

关于行业网站优化我写的只是 SEO 的操作细则并非运营思路&#xff0c;运营思路将在后期引入&#xff0c; 这个行业网站优化细则我花几天的时间进行梳理结构和整理&#xff0c; 希望大家提意见&#xff0c; 同时谢谢长 期支持本站的 SEOer。 行业站的优势在于其海量的信息&#…

java Socket多线程服务器源代码介绍

java Socket多线程服务器源代码介绍java Socket多线程在我们进行相关学习的时候需要注意不断出现的问题&#xff0c;下面我们就来看看在java Socket多线程中服务器的代码编写。java Socket多线程需要我们不断的学习&#xff0c;在学习的时候我们就会发现在服务器的配置上有不少…

Java Socket 编程——多线程网络聊天程序

Java Socket 编程——多线程网络聊天程序 首先&#xff0c;进行服务端的编程&#xff0c;作为服务端&#xff0c;编程主要按下面几个步骤进行&#xff1a;// 1. 创建socketServerSocket ss new ServerSocket(PortNumber);Socket s ss.accept(); //监听器&#xff0c;产生阻塞…

SQL Server 跨服务器 不同数据库之间复制表的数据的方法:

不同数据库之间复制表的数据的方法&#xff1a; 当表目标表存在时&#xff1a; insert into 目的数据库..表 select * from 源数据库..表 当目标表不存在时&#xff1a; select * into 目的数据库..表 from 源数据库..表 --如果在不同的SQL之间: insert into openrowset(sql…

Java多线程-----Socket通信

Java多线程-----Socket通信程序分Server和Client服务器端打开侦听的端口&#xff0c;一有客户端连接就创建两个新的线程来负责这个连接一个负责客户端发送的信息(ClientMsgCollectThread 类)&#xff0c;另一个负责通过该Socket发送数据&#xff08;ServerMsgSendThread &#…