use sync to avoid data race