Lock Cache before downloading Dart SDK on Windows (#7931)

diff --git a/bin/flutter.bat b/bin/flutter.bat
index 5f98b4f..1bdb90a 100644
--- a/bin/flutter.bat
+++ b/bin/flutter.bat
@@ -17,6 +17,7 @@
 FOR %%i IN ("%~dp0..") DO SET FLUTTER_ROOT=%%~fi
 
 SET flutter_tools_dir=%FLUTTER_ROOT%\packages\flutter_tools
+SET cache_dir=%FLUTTER_ROOT%\bin\cache
 SET snapshot_path=%FLUTTER_ROOT%\bin\cache\flutter_tools.snapshot
 SET stamp_path=%FLUTTER_ROOT%\bin\cache\flutter_tools.stamp
 SET script_path=%flutter_tools_dir%\bin\flutter_tools.dart
@@ -33,42 +34,57 @@
   EXIT /B
 )
 
+REM Ensure that bin/cache exists.
+IF NOT EXIST "%cache_dir%" MKDIR "%cache_dir%"
+
 REM To debug the tool, you can uncomment the following line to enable checked mode and set an observatory port:
 REM SET FLUTTER_TOOL_ARGS="--observe=65432 --checked"
 
-PUSHD "%flutter_root%"
-FOR /f %%r IN ('git rev-parse HEAD') DO SET revision=%%r
-POPD
+:acquire_lock
+2>NUL (
+  REM "3" is now stderr because of "2>NUL".
+  CALL :subroutine %* 2>&3 9> "%cache_dir%\flutter.bat.lock" || GOTO acquire_lock
+)
+GOTO :after_subroutine
 
-REM The following IF conditions are all linked with a logical OR. However,
-REM there is no OR operator in batch and a GOTO construct is used as replacement.
-IF NOT EXIST "%snapshot_path%" GOTO do_snapshot
-IF NOT EXIST "%stamp_path%" GOTO do_snapshot
-SET /p stamp_value=<"%stamp_path%"
-IF !stamp_value! NEQ !revision! GOTO do_snapshot
-REM Get modified timestamps
-FOR %%f IN ("%flutter_tools_dir%\pubspec.yaml") DO SET yamlt=%%~tf
-FOR %%a IN ("%flutter_tools_dir%\pubspec.lock") DO SET lockt=%%~ta
-IF !lockt! LSS !yamlt! GOTO do_snapshot
-
-GOTO after_snapshot
-
-:do_snapshot
-  MKDIR "%FLUTTER_ROOT%\bin\cache" 2> NUL
-  ECHO: > "%FLUTTER_ROOT%\bin\cache\.dartignore"
-
-  ECHO Checking Dart SDK version...
-  CALL PowerShell.exe -ExecutionPolicy Bypass -Command "& '%FLUTTER_ROOT%/bin/internal/update_dart_sdk.ps1'"
-
-  ECHO Updating flutter tool...
-  del "%flutter_tools_dir%\pubspec.lock"
-  PUSHD "%flutter_tools_dir%"
-  CALL "%pub%" get --verbosity=error --no-packages-dir
+:subroutine
+  PUSHD "%flutter_root%"
+  FOR /f %%r IN ('git rev-parse HEAD') DO SET revision=%%r
   POPD
-  CALL "%dart%" --snapshot="%snapshot_path%" --packages="%flutter_tools_dir%\.packages" "%script_path%"
-  >"%stamp_path%" ECHO %revision%
 
-:after_snapshot
+  REM The following IF conditions are all linked with a logical OR. However,
+  REM there is no OR operator in batch and a GOTO construct is used as replacement.
+  IF NOT EXIST "%snapshot_path%" GOTO do_snapshot
+  IF NOT EXIST "%stamp_path%" GOTO do_snapshot
+  SET /p stamp_value=<"%stamp_path%"
+  IF !stamp_value! NEQ !revision! GOTO do_snapshot
+  REM Get modified timestamps
+  FOR %%f IN ("%flutter_tools_dir%\pubspec.yaml") DO SET yamlt=%%~tf
+  FOR %%a IN ("%flutter_tools_dir%\pubspec.lock") DO SET lockt=%%~ta
+  IF !lockt! LSS !yamlt! GOTO do_snapshot
+
+  REM Everything is uptodate - exit subroutine
+  EXIT /B
+
+  :do_snapshot
+    MKDIR "%FLUTTER_ROOT%\bin\cache" 2> NUL
+    ECHO: > "%FLUTTER_ROOT%\bin\cache\.dartignore"
+
+    ECHO Checking Dart SDK version...
+    CALL PowerShell.exe -ExecutionPolicy Bypass -Command "& '%FLUTTER_ROOT%/bin/internal/update_dart_sdk.ps1'"
+
+    ECHO Updating flutter tool...
+    del "%flutter_tools_dir%\pubspec.lock"
+    PUSHD "%flutter_tools_dir%"
+    CALL "%pub%" get --verbosity=error --no-packages-dir
+    POPD
+    CALL "%dart%" --snapshot="%snapshot_path%" --packages="%flutter_tools_dir%\.packages" "%script_path%"
+    >"%stamp_path%" ECHO %revision%
+
+  REM Exit Subroutine
+  EXIT /B
+
+:after_subroutine
 
 CALL "%dart%" %FLUTTER_TOOL_ARGS% "%snapshot_path%" %*