参照:
http://azrael6619.iteye.com/blog/425630
一、同步方法
public synchronized void A(){
//...
}
锁定的是调用这个同步方法的对象
测试:
a、不使用这个关键字修饰方法,两个线程调用同一个对象的这个方法。
目标类:
public class BusinessLogic{
public void execute(){
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
线程类:
public class RunnableImpl implements Runnable{
BusinessLogic thread = null;
public RunnableImpl(BusinessLogic thread){
this.thread = thread;
}
public void run(){
thread.execute();
}
}
调用:
public class Main {
public static void main(String[] args) throws Exception{
BusinessLogic test = new BusinessLogic();
Runnable runnable = new RunnableImpl(test);
Thread a = new Thread(runnable, "A");
a.start();
Thread b = new Thread(runnable, "B");
b.start();
}
}
结果:
输出的数字交错在一起。说明不是同步的,两个方法在不同的线程中是异步调用的。
b、修改目标类,增加synchronized修饰:
public class BusinessLogic {
public synchronized void execute(){
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
结果:
输出的数字是有序的,首先输出A的数字,然后是B,说明是同步的,虽然是不同的线程,但两个方法是同步调用的。
注意:上面虽然是两个不同的线程,但是是同一个实例对象。下面使用不同的实例对象进行测试。
c、每个线程都有独立的TestThread对象。
目标类:
public class BusinessLogic {
public synchronized void execute(){
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
调用:
public class Main {
public static void main(String[] args) throws Exception{
BusinessLogic test = new BusinessLogic();
Runnable runnable = new RunnableImpl(test);
Thread a = new Thread(runnable, "A");
a.start();
BusinessLogic test2 = new BusinessLogic();
Runnable runnable2 = new RunnableImpl(test2);
Thread b = new Thread(runnable2, "B");
b.start();
}
}
结果:
输出的数字交错在一起。说明虽然增加了synchronized 关键字来修饰方法,但是不同的线程调用各自的对象实例,两个方法仍然是异步的。
引申:
对于这种多个实例,要想实现同步即输出的数字是有序并且按线程先后顺序输出,我们可以增加一个静态变量,对它进行加锁(后面将说明锁定的对象)。
修改目标类:
public class BusinessLogic {
private static Object lock = new Object(); //It must be a static Object
public void execute(){
synchronized(lock){
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
}
二、同步代码块
锁定一个对象,其实锁定的是该对象的引用(object reference)
谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以按上面的代码写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它必须是一个对象)来充当锁(上面的解决方法就是增加了一个状态锁)。
a、锁定一个对象,它不是静态的
public class BusinessLogic {
private Object lock=new Object(); // It is not a static Object
public void execute(){
synchronized(lock){ //增加了个锁,锁定了对象lock,在同一个类实例中,是线程安全的,但不同的实例还是不安全的。因为不同的实例有不同对象锁lock
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
}
其实上面锁定一个方法,等同于下面的:
public void execute(){
synchronized(this){
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
b、锁定一个对象或方法,它是静态的
这样锁定,它锁定的是对象所属的类
public class BusinessLogic {
public synchronized static void execute(){
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
等同于:
public class BusinessLogic {
private static Object lock = new Object(); //It must be a static Object
public void execute(){
synchronized(lock){
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
}
c、注意:
1、用synchronized 来锁定一个对象的时候,如果这个对象在锁定代码段中被修改了,则这个锁也就消失了。看下面的实例:
目标类:
public class BusinessLogic {
private static Object lock = new Object();
public void execute(){
synchronized(lock){
lock = "abc";
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
}
调用:
public class Main {
public static void main(String[] args) throws Exception{
BusinessLogic test = new BusinessLogic();
Runnable runnable = new RunnableImpl(test);
Thread a = new Thread(runnable, "A");
a.start();
BusinessLogic test2 = new BusinessLogic();
Runnable runnable2 = new RunnableImpl(test2);
Thread b = new Thread(runnable2, "B");
b.start();
}
}
不注释lock = "abc";输出是无序得。
同理:
目标类:
public class BusinessLogic {
private Object lock = new Object();
public void execute(){
synchronized(lock){
lock = "abc";
for(int i=0; i<100; i++){
System.out.println(Thread.currentThread().getName() +":" + i);
}
}
}
}
调用:
public class Main {
public static void main(String[] args) throws Exception{
BusinessLogic test = new BusinessLogic();
Runnable runnable = new RunnableImpl(test);
Thread a = new Thread(runnable, "A");
a.start();
Thread b = new Thread(runnable, "B");
b.start();
}
}
除非lock = "abc"被注释,否则输出为无序。
分享到:
相关推荐
public class Example { private int value; public synchronized void accessVal(int newVal) { value = newVal; // 其他代码 } } ``` 这里,`accessVal`方法被声明为`synchronized`。这意味着每次只有一个...
在Java编程语言中,同步代码块(synchronized blocks)是一种重要的多线程控制机制,用于保证线程安全,防止数据的不一致性。本压缩包包含了两个示例代码——Example12.java和Example13.java,它们是针对同步代码块...
public class LockExample { private final ReentrantLock lock = new ReentrantLock(); public void doSomething() { lock.lock(); try { // 执行需要同步的代码 System.out.println("执行同步代码"); } ...
6. **多线程**:Java内置对多线程的支持,你可以看到如何创建线程,使用同步机制(如`synchronized`关键字和`wait()`, `notify()`方法)来避免线程并发问题。 7. **接口与抽象类**:接口和抽象类是实现多态性的重要...
6. **多线程**:Java提供了对并发编程的良好支持,例子可能包括Thread类的使用,Runnable接口,synchronized关键字,以及线程池的创建和管理。 7. **网络编程**:如Socket编程,HTTP请求等,这对于开发网络应用的...
本示例“多线程的example”旨在探讨如何在Java中实现和管理多线程,尤其是关于锁(lock)和同步(synchronized)的概念。 一、线程的创建与运行 在Java中,有两种主要的创建线程的方式: 1. 继承`java.lang.Thread...
在本资源"JAVA code example 100 例"中,我们拥有一系列精心挑选的Java编程示例,旨在帮助开发者深入理解和应用Java语言。这个压缩包包含了从基础到高级的100个源代码实例,覆盖了Java编程的多个重要方面。下面,...
在上述代码中,`Example`类有一个`synchronized`修饰的`excute()`方法。这意味着当一个线程正在执行`excute()`方法时,其他试图进入该方法的线程将会被阻塞,直到当前线程完成执行并释放锁。因此,当`Thread1`和`...
由于它们都被`synchronized`修饰,这意味着尽管`execute()`和`execute2()`是不同的方法,但是它们仍然共享相同的锁,即`Example`对象本身。因此,即使有多个线程(如`Thread1`和`Thread2`)分别调用这两个方法,它们...
6. **多线程**:了解Thread类,实现Runnable接口,线程同步(synchronized关键字,wait(),notify(),notifyAll())和线程池的使用。 7. **反射机制**:通过反射动态获取类信息,创建对象,调用方法,访问字段。 8...
例子将展示如何创建和管理线程,以及如何使用synchronized关键字和wait/notify机制来处理并发问题。 9. **Java Swing和JavaFX**:这两个是Java的图形用户界面库,用于构建桌面应用。示例可能包含创建窗口、按钮、...
在本压缩包“java-Example-21-30.rar_example 30”中,包含的是Java编程语言的实用示例代码,涵盖了从第21个到第30个实例。这些实例旨在帮助开发者深入理解和掌握Java编程的核心概念与技术。通过对这些例子的学习,...
SemaphoreExample example = new SemaphoreExample(); Thread thread1 = new Thread(() -> example.criticalSection()); Thread thread2 = new Thread(() -> example.criticalSection()); thread1.start(); ...
7. **多线程**:学习如何创建和管理线程,理解同步和互斥的概念,以及使用synchronized关键字和wait/notify机制。 8. **异常处理**:学习Java的异常处理机制,如何抛出和捕获异常。 9. **泛型**:理解泛型的作用,...
Java提供了ExecutorService、Thread、synchronized关键字等工具来处理并发问题。 4. **设计模式**:如工厂模式、观察者模式等,可以用于创建和管理pipeline中的组件,以及处理数据变化的事件。 5. **函数式编程**...
4. **动画**:SVG支持通过`<animate>`元素或SMIL(Synchronized Multimedia Integration Language)来创建动画效果。 5. **JavaScript交互**:通过JavaScript,可以动态地修改SVG元素的属性,实现交互式图形。例如,...
5. **多线程(Multithreading)**:Java内核支持多线程编程,提供了Thread类和Runnable接口,以及同步控制机制如synchronized关键字、wait()、notify()和notifyAll()方法。 6. **反射(Reflection)**:Java反射允许...
在示例代码中,你可以看到如何创建和管理线程,以及如何使用同步机制(如synchronized关键字和Lock接口)来避免线程安全问题。 最后,反射和注解是Java的高级特性。反射允许程序在运行时动态地获取类的信息并操作类...
"java-Example-31-40.rar_40"这个压缩包包含了一组实用的Java编程示例,涵盖了从第31个到第40个例子,这些都是在实际开发中可能会遇到的常见问题和解决方案。下面,我们将深入探讨这些实例,提取出重要的知识点,以...