在JAVA中,线程与线程之间的数据是共享的,因此,当多个线程同时改变相同的对象,线程会相互倾轧。根据线程访问数据的不同线性,会产生被腐蚀的对象。
为了避免这种现象,我们需要对需要保护的对象上锁,这样在同一时间只能有一个线程访问这个数据,而其他的线程进入等待队列,知道这个线程访问完数据并释放锁,等待队列中的线程才能获得锁。
上锁的方法有多种,这里只写出常用的三种
1.synchronized代码块
synchronized (object)
{
}
例如:
public class TraditionalThreadSynchronized { public static void main(String[] args) { final Outputter output = new Outputter(); new Thread() { public void run() { output.output("zhangsan"); }; }.start(); new Thread() { public void run() { output.output("lisi"); }; }.start(); } } class Outputter { public void output(String name) { // TODO 为了保证对name的输出不是一个原子操作,这里逐个输出name的每个字符 synchronized (this) { for(int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); // Thread.sleep(10); } } } }
object 必须是需要互斥的多个线程间的共享对象。
因此下面这段代码的锁是无效的
public class TraditionalThreadSynchronized { public static void main(String[] args) { final Outputter output = new Outputter(); new Thread() { public void run() { output.output("zhangsan"); }; }.start(); new Thread() { public void run() { output.output("lisi"); }; }.start(); } } class Outputter { public void output(String name) { // TODO 为了保证对name的输出不是一个原子操作,这里逐个输出name的每个字符 Object object=new Object(); synchronized (object) { for(int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); // Thread.sleep(10); } } } }
2.synchronized 方法
public synchronized void output(String name) { // TODO 线程输出方法 for(int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); } }
这种方式就相当于用this锁住整个方法内的代码块,如果用synchronized加在静态方法上,就相当于用××××.class锁住整个方法内的代码块。使用synchronized在某些情况下会造成死锁,死锁问题以后会说明。使用synchronized修饰的方法或者代码块可以看成是一个原子操作。
每个锁对都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线 程,当一个线程被唤醒(notify)后,才会进入到就绪队列,等待CPU的调度,反之,当一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒, 这个涉及到线程间的通信,一个线程执行互斥代码过程如下:
1. 获得同步锁;
2. 清空工作内存;
3. 从主内存拷贝对象副本到工作内存;
4. 执行代码(计算或者输出等);
5. 刷新主内存数据;
6. 释放同步锁。
所以,synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性。
3.lock方法
Lock lc=new ReentrantLock();
lc.lock();
// do work
lc.unlock();
这种方法一般不推荐使用
相关推荐
你还在用synchronized?线程安全相关知识深入剖析
Java多线程与线程安全...总之,Java多线程与线程安全实践-基于Http协议的断点续传项目是一个很好的Java毕业设计项目,可以帮助学生深入理解Java多线程编程、线程安全和网络编程等知识点,同时也具有较高的实用价值。
java线程和容器专题课程第一部分,共两部分。详细讲解java线程的一些知识和技术原理。...在多线程中,一般对于static用的比较多,其特殊性起到了共享数据的作用,而Random提供了随机数且它是线程安全的。
CopyOnWriteArrayList是Java中的一种线程安全的数组列表,用于解决多线程环境下的数据共享问题。CopyOnWriteArrayList使用写时复制机制,确保多个线程可以安全地访问该数组列表。 Thread安全 Thread安全是Java多...
Java 线程知识点总结 Java 线程是一种轻量级的进程,它是进程中的一个独立的控制单元,线程在控制着进程的执行。每个进程至少有一个线程。Java 虚拟机(JVM)启动时会有一个进程 java.exe,该进程至少有一个线程...
本实验报告对Java多线程编程的基础知识进行了详细的实验和分析,并提供了实验中的关键代码。本实验报告对Java多线程编程的学习有着重要的参考价值。 知识点总结: * Java多线程编程的基础知识 * 线程的创建和管理 ...
Java 中高级核心知识全面解析 Java 是一种面向对象的编程语言,它具有平台独立性、多线程、网络编程等特点。本文将对 Java 中的高级核心知识进行全面解析,从基础知识到高级特性,全方位解析 Java 的核心技术。 一...
您将了解线程安全、死锁、线程池、线程上下文切换、线程同步和互斥、volatile关键字、synchronized关键字等重要知识点。此外,还探讨了线程间通信、线程优先级、守护线程、线程组、可重入锁、线程局部变量等关键概念...
线程安全 保护“共享数据” 低级并发工具 原子变量 锁(内部锁和显式锁) 线程安全容器 同步容器 并发容器 阻塞队列 高级线程协作工具 信号量 闭锁 关卡 fork-join Executor部分 ...
作为一个Java web开发人员,很少也不需要去处理线程,因为服务器已经帮我们处理好了。记得大一刚学Java的时候,老师带着我们做了一个局域网聊天室,用到了AWT、Socket、多线程、I/O,编写的客户端和服务器,当时做...
部分主要阐述Thread的基础知识,详细介绍线程的API使用、线程安全、线程间数据通信,以及如何保护共享资源等内容,它是深入学习多线程内容的基础
1.5线程安全的分类 1.6线程安全的方法 二、线程基础 2.1状态 2.2使用方式 2.3基础机制 2.4中断 2.5互斥同步 2.6线程合作 三、Synchronized 详解 3.1 使用 3.2 原理分析 3.3 JVM中锁的优化 3.4 ...
AtomicInteger 是 Java 中的一种原子整数类,它提供了一种线程安全的整数操作机制。AtomicInteger 可以用来实现线程安全的计数器、锁机制等。 6. 用过 ThreadLocal 吗?怎么用的? ThreadLocal 是 Java 中的一种...
知识点1: SimpleDateFormat的非线程安全性 SimpleDateFormat类不是线程安全的,这意味着在多线程环境下,如果多个线程同时访问同一个SimpleDateFormat实例,可能会导致各种问题,例如转化的时间不正确、报错、线程...
【ASP.NET编程知识】实例解析Java中的synchronized关键字与线程安全问题.docx
Java多线程与并发系列知识点 Java多线程与并发系列知识点...Java多线程与并发系列知识点还包括线程安全、锁机制、并发集合、并发编程的设计模式等多方面的知识点。这些知识点都是Java开发人员需要掌握的重要知识点。
* 线程安全:Java线程可以共享资源,但是需要同步机制来避免数据不一致。 * 线程调度:Java线程的调度是由JVM来管理的,包括线程的创建、启动、阻塞和死亡等。 Java内存区域 Java内存区域是Java语言的一种基本概念...
java中的线程安全,是java中的一个重要知识点,同时也是面试中经常问道的问题
线程安全:Java中的线程安全,包括同步方法和同步块等。 死锁:Java中的死锁,包括如何避免死锁和如何解除死锁。 性能优化:Java中的性能优化,包括JVM参数调优、代码优化、使用并发框架等。 并行计算:Java中的并行...
Java 集合框架的线程安全是 Java 程序员需要掌握的重要知识点。了解 Java 集合框架中的线程安全等级可以帮助 Java 程序员在进行并发编程时更加高效地利用 Java 集合框架,避免并发编程的陷阱,提高程序的可靠性和...