synchronized同步方法
方法内的变量为线程安全
方法中的变量不存在非线程安全问题,永远都是线程安全的,这个是由于方法内部变量是私有的特性造成的。
实例变量为非线程安全
这个在上一节中提到过,解决的方法就是在相对应的方法前加上关键字synchronized即可。
多个对象多个锁
package multiply.com.test;
public class Run {
public static void main(String[] args) {
HasSelfPrivateNum numRef1 = new HasSelfPrivateNum();
HasSelfPrivateNum numRef2 = new HasSelfPrivateNum();
ThreadA aThread = new ThreadA(numRef1);
ThreadB bThread = new ThreadB(numRef2);
aThread.start();
bThread.start();
}
}
package multiply.com.test;
public class ThreadA extends Thread {
private HasSelfPrivateNum numRef;
public ThreadA(HasSelfPrivateNum numRef) {
this.numRef = numRef;
}
@Override
public void run() {
super.run();
numRef.addI("a");
}
}
package multiply.com.test;
public class ThreadB extends Thread {
private HasSelfPrivateNum numRef;
public ThreadB(HasSelfPrivateNum numRef) {
this.numRef = numRef;
}
@Override
public void run() {
super.run();
numRef.addI("b");
}
}
package multiply.com.test;
public class HasSelfPrivateNum {
private int num = 0;
public synchronized void addI(String username) {
try {
if ("a".equals(username)) {
num = 100;
System.out.println("a set over!");
Thread.sleep(1600);
} else {
num = 200;
System.out.println("b set over!");
}
System.out.println(username + " num = " + num);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
b set over! a set over! b num = 200 a num = 100 异步运行,不存在脏读的现象。
synchronized方法与锁对象
package multiply.com.test;
public class Run {
public static void main(String[] args) {
MyObject object = new MyObject();
ThreadA aThread = new ThreadA(object);
ThreadB bThread = new ThreadB(object);
aThread.setName("A");
bThread.setName("B");
aThread.start();
bThread.start();
}
}
package multiply.com.test;
public class ThreadA extends Thread {
private MyObject object;
public ThreadA(MyObject object) {
this.object = object;
}
@Override
public void run() {
super.run();
object.methodA();
}
}
package multiply.com.test;
public class ThreadB extends Thread {
private MyObject object;
public ThreadB(MyObject object) {
this.object = object;
}
@Override
public void run() {
super.run();
object.methodB();
}
}
package multiply.com.test;
public class MyObject {
public synchronized void methodA() {
try {
System.out.println("begin method A thread name = " + Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void methodB() {
try {
System.out.println("begin method B thread name = " + Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
begin method B thread name = B begin method A thread name = A end end 下面标注的更关键:
synchronized锁重入
出现异常,锁自动释放
同步不具有继承性
synchronized同步语句块
synchronized同步语句块的使用
package multiply.com.test;
public class Run {
public static void main(String[] args) {
ObjectService service = new ObjectService();
ThreadA aThread = new ThreadA(service);
ThreadB bThread = new ThreadB(service);
aThread.setName("a");
bThread.setName("b");
aThread.start();
bThread.start();
}
}
package multiply.com.test;
public class ThreadA extends Thread {
private ObjectService service;
public ThreadA(ObjectService service) {
this.service = service;
}
@Override
public void run() {
super.run();
service.serviceMethod();
}
}
package multiply.com.test;
public class ThreadB extends Thread {
private ObjectService service;
public ThreadB(ObjectService service) {
this.service = service;
}
@Override
public void run() {
super.run();
service.serviceMethod();
}
}
package multiply.com.test;
public class ObjectService {
private String getData1;
private String getData2;
public void serviceMethod() {
try {
System.out.println("begin task");
Thread.sleep(2000);
String privateGetData1 = "长时间处理任务后返回值1 threadName="+Thread.currentThread().getName();
String privateGetData2 = "长时间处理任务后返回值2 threadName="+Thread.currentThread().getName();
synchronized(this)
{
getData1 = privateGetData1;
getData2 = privateGetData2;
}
System.out.println(getData1);
System.out.println(getData2);
System.out.println("end task");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
begin task begin task 长时间处理任务后返回值1 threadName=b 长时间处理任务后返回值2 threadName=b end task 长时间处理任务后返回值1 threadName=a 长时间处理任务后返回值2 threadName=a end task
将任意对象作为对象检测器
package multiply.com.test;
public class Run {
public static void main(String[] args) {
Service service = new Service();
ThreadA aThread = new ThreadA(service);
ThreadB bThread = new ThreadB(service);
aThread.setName("A");
bThread.setName("B");
aThread.start();
bThread.start();
}
}
package multiply.com.test;
public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service) {
this.service = service;
}
@Override
public void run() {
super.run();
service.a();
}
}
package multiply.com.test;
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service) {
this.service = service;
}
@Override
public void run() {
super.run();
service.b();
}
}
package multiply.com.test;
public class Service {
private String anyString = new String();
public void a() {
try {
synchronized (anyString) {
System.out.println("a begin");
Thread.sleep(3000);
System.out.println("a end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public void b() {
System.out.println("b begin");
System.out.println("b end");
}
}
细化验证三个结论
package multiply.com.test;
public class Run {
public static void main(String[] args) {
Service service = new Service();
MyObject object = new MyObject();
ThreadA aThread = new ThreadA(object, service);
ThreadB bThread = new ThreadB(object);
aThread.setName("a");
bThread.setName("b");
aThread.start();
bThread.start();
}
}
package multiply.com.test;
public class ThreadA extends Thread {
private MyObject object;
private Service service;
public ThreadA(MyObject object, Service service) {
this.object = object;
this.service = service;
}
@Override
public void run() {
super.run();
service.testMethod1(object);
}
}
package multiply.com.test;
public class ThreadB extends Thread {
private MyObject object;
public ThreadB(MyObject object) {
this.object = object;
}
@Override
public void run() {
super.run();
object.speedPrintString();
}
}
package multiply.com.test;
public class Service {
public void testMethod1(MyObject object) {
synchronized (object) {
try {
System.out.println("test method 1 __getLock time = " + System.currentTimeMillis() + " Run thread name = " + Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("test method 1 releaseLock time = " + System.currentTimeMillis() + " Run thread name = " + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package multiply.com.test;
public class MyObject {
public void speedPrintString() {
synchronized (this) {
System.out.println("speedPrintString __getLock time = " + System.currentTimeMillis() + " Run thread name " + Thread.currentThread().getName());
System.out.println("------------------------------------------------");
System.out.println("speedPrintString releaseLock time = " + System.currentTimeMillis() + " Run thread name " + Thread.currentThread().getName());
}
}
}
speedPrintString __getLock time = 1634822778915 Run thread name b
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
------------------------------
?????????????????????????????? speedPrintString releaseLock time = 1634822778915 Run thread name b test method 1 __getLock time = 1634822778915 Run thread name = a test method 1 releaseLock time = 1634822783917 Run thread name = a
|