`
wx1568905209
  • 浏览: 25151 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

线程(一)

 
阅读更多

一、线程安全锁-synchronized

1、什么是线程安全:当多个线程访问一个类对象或方法时,该对象或方法都能表现正确行为,就是线程安全

2、synchronized:可以用在代码块或方法上

public class SynchronizedTest extends Thread {

    private int count = 5;

    @Override
    public void run() {
        count --;
        System.out.println(Thread.currentThread().getName() + "---count:" + count);
    }

    public static void main(String[] args) {
        SynchronizedTest synchronizedTest = new SynchronizedTest();
        Thread thread = new Thread(synchronizedTest, "t1");
        Thread thread2 = new Thread(synchronizedTest, "t2");
        Thread thread3 = new Thread(synchronizedTest, "t3");
        Thread thread4 = new Thread(synchronizedTest, "t4");
        Thread thread5 = new Thread(synchronizedTest, "t5");
        thread.start();
        thread2.start();
        thread3.start();
        thread4.start();
        thread5.start();
    }
}

结果:
t1---count:4
t2---count:3
t3---count:2
t4---count:1
t5---count:0

加上synchronized

 @Override
    public synchronized void run() {
        count --;
        System.out.println(Thread.currentThread().getName() + "---count:" + count);
    }


t1---count:4
t5---count:3
t4---count:2
t3---count:1
t2---count:0

synchronized是以把锁,当多个线程访问方法时,会以排队的方式进行处理(根据CPU分配,所以上面线程并不是按12345的顺序),线程访问时,会先尝试拿锁,如果拿到锁,就执行synchronized方法,如果拿不到,就会不断尝试去拿锁,直到拿到为止。而且是多个线程竞争拿锁。

3、锁(对象锁、独占锁)

public class SynchronizedTest2 {

    public synchronized void print(String name) {
        int type = 0;
        if (name.equals("张三")) {
            type = 1;
            System.out.println("name:" + name + "  type:" + type);
        } else {
            type = 2;
            System.out.println("name:" + name + "  type:" + type);
        }
        System.out.println("hello, I'm is " + name);
    }

    public static void main(String[] args) {
        final SynchronizedTest2 test1 = new SynchronizedTest2();
        final SynchronizedTest2 test2 = new SynchronizedTest2();

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                test1.print("张三");
            }
        });

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                test2.print("李四");
            }
        });

        t1.start();
        t2.start();
    }
}

结果:
name:李四  type:2
name:张三  type:1
hello, I'm is 李四
hello, I'm is 张三

从结果看,print()并没有被锁,因为我们希望是打印name时,hello也紧跟着打印,但是上面的情况明显没锁到。究竟是怎么呢?

是因为两个线程t1,t2执行的锁不是一把锁,等于有两个人,各进到两个厕所里,并没有任何冲突,如果再来一个人,到另外第三个厕所。 所以这时,需要在方法上加static,方法加static后,方法锁属于类对象,那么类下的所以对象拥有一把锁

public static synchronized void print(String name) {
        int type = 0;
        if (name.equals("张三")) {
            type = 1;
            System.out.println("name:" + name + "  type:" + type);
        } else {
            type = 2;
            System.out.println("name:" + name + "  type:" + type);
        }
        System.out.println("hello, I'm is " + name);
    }

name:张三  type:1
hello, I'm is 张三
name:李四  type:2
hello, I'm is 李四

这时的锁属于独占锁,静态方法加synchornized锁,属于类级别锁,无论实例化多个对象,都是一把锁。非静态的都是对象锁

 

4、对象锁的同步、异步

同步:访问加了synchronized的方法或代码块

public class SychonirzedTest3 {

    public synchronized void method1() {
        System.out.println("线程名称:" + Thread.currentThread().getName());
        try {
            Thread.sleep(1000 * 5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public  void method2() {
        System.out.println("线程名称:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        final SychonirzedTest3 test = new SychonirzedTest3();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                test.method1();
            }
        });

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                test.method2();
            }
        });

        t1.start();
        t2.start();
    }
}

上面定义了一个同步方法、异步方法

我们在method1()加了同步,并休眠5秒,结果发现:method1()执行完了,马上执行method2(),说明这两个互不影响,但是如果我在method2()上加了同步,就会出现必须线程1休眠5秒后才执行,这就是对象锁同步

5、同步要注意几点:setValue/getValue都要保证synchronized,避免脏读;可重入,比如父类方法用了,子类也要用,方法嵌套可以以用

6、synchronized代码块,有时一个synchronized方法需要执行很长时间,那其他线程就需要等候很长时间,这时可以使用代码块,减小锁的粒度

public void method2() {
    synchronized (SynchronizedCode.class) {
        for (int i=0; i<5; i++) {
            System.out.println(Thread.currentThread().getName() + "  method2");
        }
    }
}


public void method3() {
    synchronized (this) {
        System.out.println(Thread.currentThread().getName() + "  method2");
    }
}
public static void main(String[] args) {
        final SynchronizedCode synchronizedCode = new SynchronizedCode();

//        for (int i=0; i<5; i++) {
            Thread thread = new Thread(new Runnable() {
                public void run() {
                    synchronizedCode.method1();
                }
            }, "name" + 1);
            thread.start();
//        }

//        for (int i=0; i<5; i++) {
            Thread thread2 = new Thread(new Runnable() {
                public void run() {
                    synchronizedCode.method2();
                }
            }, "name2" + 2);
            thread2.start();
//        }
    }

synchronized(this)指的是调用该方法的引用,对应上面代码的synchronizedCode

synchronized(SynchronizedTest.class):指的是类本身,这种与在synchronized方法上加static一样,独立锁

 

转载于:https://my.oschina.net/u/2504766/blog/757517

分享到:
评论

相关推荐

    线程异步工作,当一个线程结束时异步通知另一线程

    在多线程编程中,线程间的协作是关键任务之一,尤其当需要一个线程在完成特定工作后通知另一个线程继续执行时。这个过程通常涉及到线程同步和异步的概念。本文将深入探讨线程异步工作以及如何在C++中实现一个线程在...

    qt QTcpServer多线程

    QTcpServer多线程 ...注意:如果你想处理在另一个线程一个新的QTcpSocket对象传入连接,您必须将socketDescriptor传递给其他线程,并创建了QTcpSocket对象存在并使用其setSocketDescriptor()方法。

    java多线程查询数据库

    在Java编程中,多线程查询数据库是一种常见的优化策略,特别是在处理大数据量或者需要并行执行多个查询时。本文将详细探讨如何利用Java的多线程技术和线程池来实现并发查询数据库,以及相关的文件`BatchDataUtil....

    Linux编程技术-实验4 多线程编程.doc

    线程一完成以下操作: * 设置全局变量 key 的值为字符串“hello world” * 打印 3 次字符串“当前线程 ID:key 值” * 接收到线程二发送的取消请求信号后退出 * 结束的时候打印字符串“thread1 ,exited!:key 值...

    Java多线程笔记

    一个新构建的线程对象是由其父线程来进行空间分配的,而子线程继承了父线程的是否为 Daemon、优先级和加载资源的 contextClassLoader 以及可继承的 ThreadLocal,同时会分配一个唯一的 ID 来标识这个线程。...

    C++线程库介绍

    例如,`yield` 函数、`get_id` 函数返回当前线程的标识、`sleep_for` 函数停止当前线程一段时间、`sleep_until` 函数停止当前线程直到某个时间点。 3. Mutual exclusion(互斥量) C++11 的线程库提供了多种互斥量...

    vivado设置多线程一劳永逸的方法

    vivado设置多线程一劳永逸的方法

    多线程面试相关知识点

    多线程编程的目的,就是"最大限度地利用CPU资源",当某一线程的处理不需要占用CPU而只和I/O等资源打交道时,让需要占用CPU资源的其它线程有机会获得CPU资源。从根本上 说,这就是多线程编程的最终目的。 单线程...

    计算机操作系统实验_创建GeekOS内核线程.pdf

    从结果中可以看出,两个线程共享CPU时间,同一时间只能运行一个线程,且运行哪一个线程是随机的。 3. 自行设计个性化的内核线程,给出运行结果。 在这个实验中,我们自行设计了一个个性化的内核线程,实现了两个...

    多线程的另一个例子

    利用线程池开多个线程在linux下运行

    环形buffer无锁一线程写一线程读

    使用场景为一个线程写一个线程读完全不需要锁。可以设定buffer的初始块及数量,初始块是固定大小的,当需要扩环时会动态创建块即不像其它的库块满了就写失败了,当释放时会将动态创建的块还给系统,初始块还给自己的...

    MFC多线程 工作者线程 用户界面线程

    在MFC应用中,例如,可以创建一个工作者线程用于长时间的数据库查询,而用户界面线程则保持正常响应,展示查询进度。当查询完成后,工作者线程通过PostThreadMessage向用户界面线程发送消息,告知查询结果,由用户...

    实现一个数据单元,包括学号和姓名两部分。编写两个线程,一个线程往数据单元中写,另一个线程往出读。要求每写一次就往出读一次。

    在IT领域,多线程是一种常见的编程模型,用于提高程序的执行效率和并发性。本实验的任务是设计并实现一个数据单元,该单元包含学号和姓名两个字段,并且使用两个线程,一个用于写入数据,另一个用于读取数据。这种...

    C# 如何挂起线程、休眠线程和终止线程(源码例)

    - **事件(Events)**:通过WaitHandle类的子类(如ManualResetEvent或AutoResetEvent)来同步线程,一个线程等待特定事件发生,另一个线程触发事件。 - **条件变量(Conditional Variables)**:允许线程在满足...

    到底一个线程占用多少内存

    综上所述,线程的内存占用不是一个固定的值,它受多种因素影响,包括操作系统、线程类型(主线程或子线程)、编译器设置以及程序的具体运行行为。因此,优化线程内存使用时需要综合考虑这些因素,以实现更高效、更...

    Java实现消费者与生产者两个线程问题

    用Java实现消费者与生产者两个线程进行调度

    TCP-接收线程和发送线程

    在这个项目中,“TCP-接收线程和发送线程”是一个C/C++实现的多线程编程示例,旨在展示如何在服务器端和客户端之间有效地管理数据的接收和发送。以下将详细介绍相关的知识点。 首先,我们要理解TCP的基本原理。TCP...

    Python并发:多线程与多进程的详解

    本篇概要 1.线程与多线程 2.进程与多进程 ...一个线程可以看成是一个有序的指令流(完成特定任务的指令),并且可以通过操作系统来调度这些指令流。 线程通常位于进程程里面,由一个程序计数器、一个堆栈

    启动两个线程,一个线程打印1~52,另一个线程打印A~Z

    启动两个线程,一个线程打印1~52,另一个线程打印A~Z

    多线程编程

    例如,进程A可以有线程一、线程二和线程三,它们都访问同一个用户地址空间,但各自执行不同的任务。 线程机制主要有以下几种类型: 1. 用户级线程:线程管理完全由用户空间的线程库完成,操作系统不直接参与。当一...

Global site tag (gtag.js) - Google Analytics