展示一下线程同步问题,创建两个线程,执行同一个对象的输出方法。
public class PrintChar { public void output(String name) { try { for (int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); Thread.sleep(1); } } catch (InterruptedException e) { } } }
public static void main(String[] args) { final PrintChar printer = new PrintChar(); new Thread() { public void run() { printer.output("aaaaa"); }; }.start(); new Thread() { public void run() { printer.output("bbbbb"); }; }.start(); }
运行结果:
abababbaba
显然输出的字符串被打乱了,我们期望的输出结果是aaaaabbbbb,这就是线程同步问题,我们希望output方法被一个线程完整的执行完之后再切换到下一个线程。Java中使用锁机制保证一段代码在多线程执行时是互斥的。
一,内置锁:synchronized关键字。
Java中使用synchronized保证一段代码在多线程执行时是互斥的,有两种用法:
1. 使用synchronized将需要互斥的代码包含起来,并上一把锁。
public class PrintChar { public void output(String name) { try { synchronized (this) { for (int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); Thread.sleep(1); } } } catch (InterruptedException e) { } } }
这把锁必须是需要互斥的多个线程间的共享对象,像下面的代码是没有意义的。
public class PrintChar { public void output(String name) { try { Object obj = new Object(); synchronized (obj) { for (int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); Thread.sleep(1); } } } catch (InterruptedException e) { } } }
每次进入该代码块都会创建一个新的obj,这个锁显然每个线程都会创建,没有意义。
2. 将synchronized加在需要互斥的方法上。
public class PrintChar { public synchronized void output(String name) { try { for (int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); Thread.sleep(1); } } catch (InterruptedException e) { } } }
这种方式就相当于用this锁住整个方法内的代码块,如果用synchronized加在静态方法上,就相当于用××××.class锁住整个方法内的代码块。使用synchronized在某些情况下会造成死锁。使用synchronized修饰的方法或者代码块可以看成是一个原子操作。
每个锁都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线 程,当一个线程被唤醒(notify)后,才会进入到就绪队列,等待CPU的调度,反之,当一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒, 这个涉及到线程间的通。看我们的例子,当第一个线程执行输出方法时,获得同步锁,执行输出方法,恰好此时第二个线程也要执行输出方 法,但发现同步锁没有被释放,第二个线程就会进入就绪队列,等待锁被释放。一个线程执行互斥代码过程如下:
1. 获得同步锁;
2. 清空工作内存;
3. 从主内存拷贝对象副本到工作内存;
4. 执行代码(计算或者输出等);
5. 刷新主内存数据;
6. 释放同步锁。
所以,synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性。
相关推荐
java多线程中synchronized关键字的用法 解压密码 www.jiangyea.com
java的线程同步机制synchronized关键字的理解_.docx
java基本教程之synchronized关键字java多线程教程共19页.pdf.zip
Java多线程synchronized关键字详解(六)共5页.pdf.zip
四、 使用synchronized关键字要注意以下四点 39 五、 关于同步和锁定的一些问题 41 Java线程:并发协作-线程的交互 47 Java线程:并发协作-生产者消费者模型 52 Java线程:并发协作-死锁 55 Java线程:线程之间的...
Java 中多线程的同步依靠的是对象锁机制,synchronized关键字就是利用了封装对象锁来实现对共享资源的互斥访问。下面这篇文章主要介绍了java线程与synchronized关键字的相关资料,需要的朋友可以参考下。
线程安全,使用synchronized关键字
实例解析Java中的synchronized关键字与线程平安问题_.docx
主要为大家详细介绍了java多线程编程之Synchronized关键字,感兴趣的朋友可以参考一下
Java的synchronized关键字用于修饰线程同步,用以线程资源共享的目的等,下面就带来简单的Java多线程编程中synchronized关键字的基础用法讲解
【ASP.NET编程知识】实例解析Java中的synchronized关键字与线程安全问题.docx
主要介绍了Java 多线程synchronized关键字详解(六)的相关资料,需要的朋友可以参考下
现有一成员变量 Test,当线程 A 调用 Test 的 synchronized 方法,线程 A 获得 Test 的同步锁,同时,线程 B 也去调用 Test 的 synchronized 方法,此时线程 B 无法获得 Test 的同步锁,必须等待线程 A 释放 Test 的...
synchronized关键字不属于方法特征签名的一部分,所以可以在覆盖方法的时候加上去。也就是说,在父类的方法声明上可以没有synchronized关键字,而在子类覆盖该方法时加上synchronized关键字。 注意:使用...
Lock接口与synchronized关键字在Java并发编程中都是用于实现同步机制的重要工具,但它们在使用方式、功能特性以及灵活性等方面存在一些显著的差异。 首先,从使用方式上来看,synchronized是Java语言内置的关键字,...
比较详细的方法解读,更清晰的理清头绪 同步方法:synchronized关键字来声明 synchronized 方法。
本资源致力于向您介绍 ...介绍如何使用 synchronized 关键字来实现线程的同步和阻塞。 线程间通信: 详解线程间通信的方法,包括 wait、notify 和 notifyAll 方法的使用。讲解如何通过这些方法实现线程的协作和同步。
开启了10个线程,每个线程都累加了10000000次,如果结果正确的话总数应该是10*10000000=1000000000.可是运行多次结果都不是这个数,而且每次运行结果都不一样。 线程安全问题主要来源于JMM的设计,主要集中在主内存...
synchronized关键字是Java提供的一种内建的同步机制,它可以确保同一时刻最多只有一个线程执行该段代码,从而保证线程安全。 volatile关键字 volatile关键字可以保证变量的可见性,当一个线程修改了volatile变量的值...