Synchronized是线程同步关键字
第一种:
属于锁当前对象,方法锁和synchronized (this)属于一个锁
public class ReentrantThread {
public static void main(String[] args) throws InterruptedException {
ReentrantObject reentrantObject=new ReentrantObject();
Thread t1=new MyThread(reentrantObject);
t1.start();
Thread t2=new HisThread(reentrantObject);
t2.start();
}
}
class MyThread extends Thread{
private ReentrantObject reentrantObject;
public MyThread(ReentrantObject reentrantObject){
this.reentrantObject=reentrantObject;
}
@Override
public void run() {
try {
reentrantObject.say1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class HisThread extends Thread{
private ReentrantObject reentrantObject;
public HisThread(ReentrantObject reentrantObject){
this.reentrantObject=reentrantObject;
}
@Override
public void run() {
try {
reentrantObject.say2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ReentrantObject{
public synchronized void say1() throws InterruptedException {
System.out.println("say1");
Thread.sleep(5000);
}
public void say2() throws InterruptedException {
synchronized (this){
System.out.println("say2");
Thread.sleep(2000);
}
}
}
第二种:
静态方法锁和synchronized(ReentrantObject.class)是一个锁
public class ReentrantThread {
public static void main(String[] args) throws InterruptedException {
ReentrantObject reentrantObject=new ReentrantObject();
Thread t1=new MyThread(reentrantObject);
t1.start();
Thread t2=new HisThread(reentrantObject);
t2.start();
}
}
class MyThread extends Thread{
private ReentrantObject reentrantObject;
public MyThread(ReentrantObject reentrantObject){
this.reentrantObject=reentrantObject;
}
@Override
public void run() {
try {
reentrantObject.say1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class HisThread extends Thread{
private ReentrantObject reentrantObject;
public HisThread(ReentrantObject reentrantObject){
this.reentrantObject=reentrantObject;
}
@Override
public void run() {
try {
reentrantObject.say2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ReentrantObject{
public synchronized static void say1() throws InterruptedException {
System.out.println("say1");
Thread.sleep(5000);
}
public static void say2() throws InterruptedException {
synchronized (ReentrantObject.class){
System.out.println("say2");
Thread.sleep(2000);
}
}
}
一般不使用常量字符串作为锁对象。
对象同步锁,锁的是当前变量指向的对象。对象的属性发生变化时,不会影响结果。
public class SynchronizedSketch {
public static void main(String[] args) throws InterruptedException {
LockObject lockObject=new LockObject();
LockThread lockThread=new LockThread(lockObject);
lockThread.setName("1");
lockThread.start();
Thread.sleep(1000);
LockThread lt=new LockThread(lockObject);
lt.setName("2");
lt.start();
}
static class LockObject{
String name;
}
static class LockThread extends Thread{
LockObject lockObject;
public LockThread(LockObject lockObject){
this.lockObject=lockObject;
}
@Override
public void run() {
synchronized (lockObject){
System.out.println(this.getName()+"线程执行了");
lockObject.name="4";
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+"线程执行完了");
}
}
}
}
执行结果:
1线程执行了
1线程执行完了
2线程执行了
2线程执行完了
上面的执行是同步的。
下面测试同步变量 的指向 发生变化时,是否会导致同步变化
public class SynchronizedSketch {
public static void main(String[] args) throws InterruptedException {
LockObject lockObject=new LockObject();
LockThread lockThread=new LockThread(lockObject);
lockThread.setName("1");
lockThread.start();
LockThread lt=new LockThread(lockObject);
lt.setName("2");
Thread.sleep(1000);
lt.start();
}
static class LockObject{
String name;
}
static class LockThread extends Thread{
LockObject lockObject;
public LockThread(LockObject lockObject){
this.lockObject=lockObject;
}
@Override
public void run() {
System.out.println("run方法执行"+this.getName());
synchronized (lockObject){
System.out.println(this.getName()+"进入线程同步块");
System.out.println(lockObject);
lockObject=new LockObject();
System.out.println(lockObject);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+"线程离开同步块");
}
}
}
}
执行结果:
run方法执行1
1进入线程同步块
com.liu.thread.SynchronizedSketch$LockObject@77355386
com.liu.thread.SynchronizedSketch$LockObject@79f2b310
run方法执行2
1线程离开同步块
2进入线程同步块
com.liu.thread.SynchronizedSketch$LockObject@77355386
com.liu.thread.SynchronizedSketch$LockObject@503c95b4
2线程离开同步块
可以看出,线程是同步的,因为2个线程锁的都是 同一个对象, 地址为386结尾。
而给lockObject加上static修饰符,则结果就不一样了
static class LockThread extends Thread{
static LockObject lockObject;
public LockThread(LockObject lockObject){
this.lockObject=lockObject;
}
运行结果:
run方法执行1
1进入线程同步块
com.liu.thread.SynchronizedSketch$LockObject@3b637176
com.liu.thread.SynchronizedSketch$LockObject@35a4886a
run方法执行2
2进入线程同步块
com.liu.thread.SynchronizedSketch$LockObject@35a4886a
com.liu.thread.SynchronizedSketch$LockObject@503c95b4
1线程离开同步块
2线程离开同步块
可以看出2个线程并不同步。因为他们访问的不是同一个对象锁。
再来一个例子:
public class SynchronizedSketch2 {
public static void main(String[] args) throws InterruptedException {
Person lockObject=new Person();
lockObject.setName("wang");
MyThread lockThread=new MyThread(lockObject);
lockThread.setName("1");
lockThread.start();
MyThread lt=new MyThread(lockObject);
lt.setName("2");
Thread.sleep(1000);
lt.start();
}
static class MyThread extends Thread{
Person person ;
public MyThread(Person person){
this.person=person;
}
@Override
public void run() {
System.out.println("run方法执行"+this.getName());
person.tellYouIamWho();
}
}
}
class Person{
private String Name;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public void tellYouIamWho(){
synchronized (Name){
System.out.println(this.getName()+"进入线程同步块");
System.out.println(Name);
Name="li";
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程离开同步块");
}
}
}
运行结果:
run方法执行1
wang进入线程同步块
wang
run方法执行2
改了进入线程同步块
改了
线程离开同步块
线程离开同步块
可以看出,并不是同步的。因为用的不是同一个对象的锁。