多线程中的synchronized小结
1.synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
2.synchronized的缺陷
synchronized是java中的一个关键字,也就是说是Java语言内置的特性。
如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:
1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;
2)线程执行发生异常,此时JVM会让线程自动释放锁。
简单的东西没必要总结,我们来看其中的几个关键点,值得体会,用一个例子说话:
1 public class Demo4 {
public static void main(String[] args) {
final Output output = new Output();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.Output1("chenchi");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.Output1("sujunjun");
}
}
}).start();
}
static class Output {
public void Output1(String name) {
synchronized (this) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public synchronized void Output2(String name) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
public synchronized static void Output3(String name) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
这个例子很简单,就是同时开启两个线程,声明一个Output内部类的对象,同时访问Output内部类的Output()方法。
1.
output.Output1("chenchi");
output.Output1("sujunjun");
很明显,打印中不会出现数据错误。synchronized ()只要保证括号里面是同一对象就不会产生错误。里面传的是this,由于两者对象都是output,所以加锁成功。
想一下,这样会成功吗?(可以)
String string = "";
public void Output1(String name) {
synchronized (string) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
这样呢?(可以)
public void Output1(String name) {
synchronized ("") {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
这样呢?(不可以)
public void Output1(String name) {
synchronized (name) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
2.
output.Output1("chenchi");
output.Output2("sujunjun");
很明显,打印中不会出现错误,因为synchronized修饰方法就是相当于给方法加锁的是当前对象。
3.
output.Output1("chenchi");
output.Output3("sujunjun");
很明显,打印会出错。为什么呢?还是因为加锁对象不是同一个了。synchronized修饰静态方法后,上锁对象为当前类对象了。
什么是当前类对象呢?就是Class类型实例,JVM在加载任何一个类时,都会创建一个Class类型的实例描述该类,并且每个类有且只有一个Class的实例描述它。
如何同步?
public void Output1(String name) {
synchronized (Output.class) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
这里改了一下Output1方法,Output.class为上锁对象,就保证了同一对象。
多线程中的synchronized小结的更多相关文章
- 多线程中的synchronized
synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码 ...
- 多线程中的Lock小结
出处:http://www.cnblogs.com/DarrenChan/p/6528578.html#undefined 1.lock和synchronized的区别 1)Lock不是Java语言内 ...
- java多线程中 volatile与synchronized的区别-阿里面试
volatile 与 synchronized 的比较(阿里面试官问的问题) ①volatile轻量级,只能修饰变量.synchronized重量级,还可修饰方法 ②volatile只能保证数据的可见 ...
- [多线程] 线程中的synchronized关键字锁
为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...
- java中多线程详解-synchronized
一.介绍 当多个线程涉及到共享数据的时候,就会设计到线程安全的问题.非线程安全其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是“脏读”.发生脏读,就是取到的数据已经被其他的线 ...
- c#多线程中Lock()关键字的用法小结
本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段 ...
- 深入理解java中的synchronized关键字
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...
- BlockingQueue阻塞队列(解决多线程中数据安全问题 可用于抢票,秒杀)
案例:一个线程类中 private static BlockingQueue<Map<String, String>> dataQueue = new LinkedBlocki ...
- java中的synchronized同步代码块和同步方法的区别
下面这两段代码有什么区别? //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized ...
随机推荐
- C# 中一些类关系的判定方法 C#中关于增强类功能的几种方式 Asp.Net Core 轻松学-多线程之取消令牌
1. IsAssignableFrom实例方法 判断一个类或者接口是否继承自另一个指定的类或者接口. public interface IAnimal { } public interface ID ...
- 当前上下文中不存在名称"Session"
http://blog.csdn.net/muzai/article/details/8862902
- C#实现foreach
方法:一.继承既有的接口 如:CollectionBase.DictionaryBase class TestForeach: CollectionBase { public void Add(str ...
- Android开发之线性布局详解(布局权重)
布局权重 线性布局支持给个别的子视图设定权重,通过android:layout_weight属性.就一个视图在屏幕上占多大的空间而言,这个属性给其设 定了一个重要的值.一个大的权重值,允许它扩大到填充 ...
- android检测网络连接状态示例讲解
网络的时候,并不是每次都能连接到网络,因此在程序启动中需要对网络的状态进行判断,如果没有网络则提醒用户进行设置 Android连接首先,要判断网络状态,需要有相应的权限,下面为权限代码(Andro ...
- 解决windows server2012 评估版本过期,系统会自动关机
解决windows server2012 评估版本过期,系统在1小时后会自动关机. 重置方法:以管理员方式运行命令行,执行slmgr.vbs /rearm,可以使授权延长180天,但是仅能延长5次.
- jmeter 发送http请求,并把获取到的请求的订单信息保存到文件中
有一个任务,需要频繁发送订单请求,并分析订单请求中有没有存在重复订单号,思路是用jmeter 发送http请求,使用正则表达式获取到订单号,并把订单号和线程号作为参数提供给java请求,在java请求 ...
- Linux内存管理机制中buffer和cache的区别
Linux内存管理机制中buffer和cache的区别理解linux内存管理,需要深入了解linux内存的各个参数含义和规则,下面介绍一下Linux操作系统中内存buffer和cache的区别. Fr ...
- WCF小问题总汇
1.Q: WCF服务有没有构造函数或者静态构造函数? A:都不可用 2.Q: WCF中如何使用全局变量? A:用session绑定,或者静态变量 3.Q: WCF在WPF一直报xaml错误 A:不要把 ...
- [svc]kill pkill killall管理进程
进程讲解 操作配置 http://www.centoscn.com/CentOS/help/2013/0809/1218.html 终止一个进程或终止一个正在运行的程序,一般是通过 kill .kil ...